Files
homelab-frontend/docs/SERVICE-USAGE.md
T

543 lines
13 KiB
Markdown
Raw Normal View History

# Service Usage Guide
Complete guide for calling all gateway-backed services via `api.riotpiao.com`.
**Table of Contents**
- [Quick Start](#quick-start)
- [Authentication](#authentication)
- [Service Map](#service-map)
- [Service-Specific Guides](#service-specific-guides)
---
## Quick Start
All services use the **X-Service** header to route requests:
```bash
curl -X POST https://api.riotpiao.com/path \
-H "X-Service: <service_name>" \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{"key": "value"}'
```
| Header | Purpose | Example |
|---|---|---|
| `X-Service` | Route to named service | `X-Service: sqs` |
| `X-Resource` | (Optional) Resource ID for auth | `X-Resource: agent-worker-queue` |
| `Authorization` | Bearer token (required for auth-protected services) | `Authorization: Bearer eyJ...` |
---
## Authentication
### Getting a Token
**From Authentik (OAuth2 client credentials flow):**
```bash
AUTHENTIK_URL=https://authentik.riotpiao.com
CLIENT_ID="your-client-id"
CLIENT_SECRET="your-client-secret"
TOKEN=$(curl -s -X POST ${AUTHENTIK_URL}/application/o/token/ \
-d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&scope=openid" \
| jq -r '.access_token')
echo $TOKEN
```
Replace `your-client-id` and `your-client-secret` with Authentik app credentials.
### Service-Specific Auth
| Service | Auth Required | Token Audience | Notes |
|---|---|---|---|
| **sqs** | ✅ Yes (gateway validates) | `sqs` | JWT signature & claims verified by gateway before proxying |
| **memory** | ❌ No | — | Pass-through (service-owned if needed) |
| **s3** (MinIO) | ❌ No | — | Native OIDC support (service-owned) |
| **iam** | ❌ No | — | Pass-through (service-owned if needed) |
| **workflow** (Temporal) | ❌ No | — | Native JWT support (service-owned) |
---
## Service Map
### Gateway Services (via X-Service header)
```
api.riotpiao.com
├─ X-Service: sqs
│ ├─ Upstream: management-service.sqs.svc.cluster.local:8080
│ ├─ Auth: ✅ Gateway validates JWT
│ └─ Docs: docs/API-sqs.md
├─ X-Service: memory
│ ├─ Upstream: poimen-memory.memory.svc.cluster.local:9090
│ ├─ Auth: ❌ Pass-through (service-owned)
│ └─ Docs: See Memory Service section below
├─ X-Service: s3
│ ├─ Upstream: minio.data.svc.cluster.local:9000
│ ├─ Auth: ❌ Native OIDC (service-owned)
│ └─ Notes: S3-compatible API
├─ X-Service: iam
│ ├─ Upstream: keycloak.iam.svc.cluster.local:8080 (or equivalent)
│ ├─ Auth: ❌ Pass-through (service-owned)
│ └─ Docs: See IAM Service section below
└─ X-Service: workflow
├─ Upstream: temporal-frontend.temporal.svc.cluster.local:7233
├─ Auth: ❌ Native JWT support (service-owned)
├─ Protocol: gRPC only (returns 501 for HTTP)
└─ Docs: docs/TEMPORAL_USAGE.md
```
### Path Prefixes (legacy, before X-Service migration)
```
api.riotpiao.com
├─ /v1/* → llm-serving (predictors: vLLM, Ollama, TEI)
├─ /sqs/* → management-service (Kafka queues)
├─ /workflow/* → Temporal (workflows)
└─ /cluster/* → atlas (topology & Argo delivery)
```
**Migration note:** X-Service routing is the current standard. Path prefixes are deprecated.
---
## Service-Specific Guides
### SQS (Kafka Queue Management)
**Endpoint:** `POST https://api.riotpiao.com/`
**Headers:**
```
X-Service: sqs
Authorization: Bearer <jwt>
```
**Send a message:**
```bash
QUEUE="agent-worker-queue"
BODY=$(printf "hello world" | base64)
curl -X POST https://api.riotpiao.com/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"messageBody\": \"$BODY\",
\"messageAttributes\": {\"values\": {}},
\"delaySeconds\": 0
}"
```
**Response:**
```json
{
"messageId": "d9f94e63-b2c1-4e9f-8c5f-8d5e3c1b7a0f",
"sequenceNumber": ""
}
```
**Receive messages (long poll, up to 20s):**
```bash
QUEUE="agent-worker-queue"
curl -X GET "https://api.riotpiao.com/?X-Service=sqs&queue=$QUEUE&maxNumberOfMessages=10&waitTimeSeconds=20" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"messages": [
{
"messageId": "d9f94e63-b2c1-4e9f-8c5f-8d5e3c1b7a0f",
"receiptHandle": "...",
"body": "aGVsbG8gd29ybGQ=",
"attributes": {"values": {}},
"receiveCount": 1,
"enqueuedAt": "2026-08-27T22:18:37Z"
}
]
}
```
**Acknowledge (delete) a message:**
```bash
RECEIPT="..."
curl -X DELETE https://api.riotpiao.com/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"receiptHandle\": \"$RECEIPT\"}"
```
**Full documentation:** [docs/API-sqs.md](API-sqs.md)
---
### Memory Service (Context & Embeddings)
**Endpoint:** `https://api.riotpiao.com/`
**Headers:**
```
X-Service: memory
```
**Status:** Service definition in progress. Uses PostgreSQL + pg_vector for embeddings.
**Planned operations:**
- Store session memory / agent context
- Query by similarity (embedding search)
- Update with approval workflow (GRM/Git review)
**Coming soon:** Full API documentation.
---
### S3 / MinIO (Object Storage)
**Endpoint:** `https://api.riotpiao.com/`
**Headers:**
```
X-Service: s3
```
**List buckets:**
```bash
curl -X GET https://api.riotpiao.com/ \
-H "X-Service: s3" \
-H "Authorization: Bearer $TOKEN"
```
**List objects in bucket:**
```bash
curl -X GET https://api.riotpiao.com/?bucket=my-bucket&prefix=data/ \
-H "X-Service: s3"
```
**Put object:**
```bash
curl -X PUT https://api.riotpiao.com/my-bucket/path/to/object.json \
-H "X-Service: s3" \
--data-binary @object.json
```
**Get object:**
```bash
curl -X GET https://api.riotpiao.com/my-bucket/path/to/object.json \
-H "X-Service: s3"
```
**Full S3/MinIO API:** Standard AWS S3 compatible API. See [MinIO docs](https://min.io/docs/minio/linux/reference/minio-mc/mc-ls.html).
---
### IAM (Identity & Access Management)
**Endpoint:** `https://api.riotpiao.com/`
**Headers:**
```
X-Service: iam
```
**List roles:**
```bash
curl -X GET https://api.riotpiao.com/roles \
-H "X-Service: iam"
```
**Get user:**
```bash
curl -X GET https://api.riotpiao.com/users/alice \
-H "X-Service: iam"
```
**Create user:**
```bash
curl -X POST https://api.riotpiao.com/users \
-H "X-Service: iam" \
-H "Content-Type: application/json" \
-d "{
\"username\": \"bob\",
\"email\": \"[email protected]\",
\"password\": \"secure-password\"
}"
```
**Assign role to user:**
```bash
curl -X POST https://api.riotpiao.com/users/bob/roles \
-H "X-Service: iam" \
-H "Content-Type: application/json" \
-d "{\"role\": \"admin\"}"
```
**Full documentation:** Service-specific (depends on IAM backend).
---
### Workflow (Temporal)
**Endpoint:** `temporal-frontend.temporal.svc.cluster.local:7233`
**Protocol:** gRPC only
**Note:** HTTP requests return **501 Not Implemented**
Use Temporal SDK directly:
```go
import "go.temporal.io/sdk/client"
c, _ := client.Dial(client.Options{HostPort: "temporal-frontend.temporal.svc.cluster.local:7233"})
defer c.Close()
// Start workflow
run, _ := c.ExecuteWorkflow(ctx, opts, YourWorkflow, args...)
var result YourWorkflowResult
run.Get(ctx, &result)
```
**Full documentation:** [docs/TEMPORAL_USAGE.md](../TEMPORAL_USAGE.md)
---
## Error Handling
### Standard Error Response
All services return errors in **RFC 9457 Problem Details** format:
```json
{
"type": "https://api.riotpiao.com/problem/not-found",
"title": "Not Found",
"status": 404,
"detail": "Resource does not exist",
"instance": "/sqs/v1/queues/nonexistent"
}
```
### Common Status Codes
| Code | Meaning | Example |
|---|---|---|
| `200 OK` | Success | Message sent, resource retrieved |
| `201 Created` | Resource created | Queue created, object uploaded |
| `204 No Content` | Success (no body) | Message deleted |
| `400 Bad Request` | Invalid input | Message body too large, invalid field |
| `401 Unauthorized` | Missing/invalid token | No Authorization header, token expired |
| `403 Forbidden` | Token valid but insufficient permissions | User lacks sqs:write permission |
| `404 Not Found` | Resource not found | Queue doesn't exist, object not found |
| `429 Too Many Requests` | Rate limit exceeded | Per-user budget exhausted |
| `502 Bad Gateway` | Upstream unreachable | Service is down or network issue |
| `501 Not Implemented` | Operation not supported | gRPC request via HTTP |
### SQS-Specific Error Mapping
SQS errors (from kmsvc) map as follows:
| gRPC Code | HTTP Status | Message |
|---|---|---|
| `NotFound` | `404` | Queue or message not found |
| `AlreadyExists` | `409` | Queue already exists |
| `InvalidArgument` | `400` | Message body too large, invalid parameter |
| `Unauthenticated` | `401` | Missing Authorization header |
| `ResourceExhausted` | `429` | Message too large, quota exceeded |
---
## Request/Response Examples
### Example 1: Send SQS Message with Auth
```bash
#!/bin/bash
GATEWAY="https://api.riotpiao.com"
AUTHENTIK="https://authentik.riotpiao.com"
CLIENT_ID="sqs-client"
CLIENT_SECRET="secret123"
QUEUE="agent-worker-queue"
# Get token
TOKEN=$(curl -s -X POST ${AUTHENTIK}/application/o/token/ \
-d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&scope=openid" \
| jq -r '.access_token')
# Send message
BODY=$(echo "process this task" | base64)
curl -X POST ${GATEWAY}/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"messageBody\": \"$BODY\"}" | jq .
```
### Example 2: Receive & Process Queue
```bash
#!/bin/bash
GATEWAY="https://api.riotpiao.com"
TOKEN="..."
QUEUE="agent-worker-queue"
MAX_MSGS=10
WAIT_SECS=20
while true; do
# Receive messages (long poll)
RESPONSE=$(curl -s -X GET "${GATEWAY}/?X-Service=sqs&queue=${QUEUE}&maxNumberOfMessages=${MAX_MSGS}&waitTimeSeconds=${WAIT_SECS}" \
-H "Authorization: Bearer $TOKEN")
MESSAGES=$(echo "$RESPONSE" | jq '.messages')
if [[ "$MESSAGES" == "null" ]]; then
echo "No messages (timeout)"
continue
fi
# Process each message
echo "$RESPONSE" | jq -r '.messages[] | @base64d' | while read -r MSG; do
echo "Processing: $MSG"
# Do work...
# Acknowledge message
RECEIPT=$(echo "$RESPONSE" | jq -r '.messages[0].receiptHandle')
curl -s -X DELETE ${GATEWAY}/ \
-H "X-Service: sqs" \
-H "Authorization: Bearer $TOKEN" \
-d "{\"receiptHandle\": \"$RECEIPT\"}"
done
done
```
### Example 3: S3 Workflow (Upload & List)
```bash
#!/bin/bash
GATEWAY="https://api.riotpiao.com"
BUCKET="my-data"
# Upload file
echo "Uploading..."
curl -X PUT ${GATEWAY}/${BUCKET}/backup-$(date +%s).tar.gz \
-H "X-Service: s3" \
--data-binary @backup.tar.gz
# List objects
echo "Listing..."
curl -X GET "${GATEWAY}/?bucket=${BUCKET}&prefix=backup-" \
-H "X-Service: s3" | jq '.Contents[]'
```
---
## Testing
### Integration Tests
Run the full test suite:
```bash
./scripts/test-integration.sh
```
Run specific service tests:
```bash
GATEWAY_URL=https://api.riotpiao.com go test -tags integration -v -run TestSQS ./internal/serviceadapter
```
### Local Testing
Start local gateway with test services:
```bash
# Terminal 1: Start gateway
CONFIG_PATH=k8s/configmap.yaml go run ./cmd/gateway
# Terminal 2: Run tests
./scripts/test-integration.sh
```
### Canary Deployment
Test a single replica before rolling out:
```bash
./scripts/test-canary.sh
```
---
## Debugging
### Check Gateway Logs
```bash
kubectl -n api logs -l app=api-gateway --tail=100 -f
```
### Port-Forward to Service
```bash
kubectl -n sqs port-forward svc/management-service 8080:8080
curl http://localhost:8080/v1/queues
```
### Verify Service Availability
```bash
kubectl get svc -A | grep -E "management-service|poimen-memory|minio|temporal"
```
### Test Direct Service Access
```bash
kubectl -n sqs exec -it deployment/management-service -- \
curl -s http://localhost:8080/v1/queues | jq .
```
---
## Rate Limits & Quotas
| Service | Limit | Notes |
|---|---|---|
| **SQS** | Per-user budget (tokens) | Budget enforced per Authentik user |
| **S3** | MinIO quotas | Set per bucket in MinIO config |
| **Memory** | Not yet enforced | Future: embeddings storage limits |
| **Temporal** | Workflow concurrency | Set in Temporal cluster config |
See [docs/QUOTAS.md](QUOTAS.md) for detailed limits.
---
## Next Steps
- [Service Adapter Documentation](../tasks/8.1-serviceadapter-crd-and-informer.md)
- [X-Service Routing](../tasks/8.2-x-service-dispatcher.md)
- [Authentication & JWT Validation](../tasks/3.1-auth-sqs-jwt-validation.md)
- [Testing Guide](../TESTING_GUIDE.md)
- [Integration Tests](../INTEGRATION_TESTS.md)