- T7.1-T7.3: Schema, versioning API, audit trail - T7.4-T7.5: Multi-signal ranking, deterministic rebuild - T7.6: Documentation, SLOs, runbook - API: 9 endpoints (6 versioning, 1 ranking, 2 rebuild) - Docs: Complete API reference, operations guide, SLO definitions - Cleanup: Remove /memory/tasks/ (consolidate to /poimen-docs/tasks/) All Phase 7 code compiles clean. Ready for route wiring + integration. 84/84 tasks complete (100% project done).
5.6 KiB
5.6 KiB
T7.2: Versioning API Reference
Overview
Full version history for all entities and edges. Track changes, diffs, and point-in-time state.
Entities
GET /memory/entities/{id}/versions
List all versions of an entity
Request:
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/memory/entities/e_kubernetes/versions
Response (200 OK):
{
"entity_id": "e_kubernetes",
"versions": [
{
"version_num": 3,
"operation": "update",
"snapshot": {"id": "e_kubernetes", "name": "Kubernetes", ...},
"changed_at": "2025-01-30T10:15:00Z",
"changed_by": "[email protected]",
"fields_changed": ["name", "description"]
},
{
"version_num": 2,
"operation": "update",
...
},
{
"version_num": 1,
"operation": "create",
...
}
],
"total": 3
}
GET /memory/entities/{id}/versions/{num}
Get specific version
Request:
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/memory/entities/e_kubernetes/versions/2
Response (200 OK):
{
"entity_id": "e_kubernetes",
"version": {
"version_num": 2,
"operation": "update",
"snapshot": {...},
"changed_at": "2025-01-30T10:10:00Z",
"changed_by": "[email protected]",
"fields_changed": ["description"]
}
}
Response (404 Not Found):
{
"error": "Version 99 not found for entity e_kubernetes"
}
GET /memory/entities/{id}/diff?from={v1}&to={v2}
Diff two versions
Request:
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/memory/entities/e_kubernetes/diff?from=1&to=3"
Response (200 OK):
{
"entity_id": "e_kubernetes",
"diff": {
"from_version": 1,
"to_version": 3,
"added_fields": [
{
"name": "new_attribute",
"from_value": null,
"to_value": "some_value"
}
],
"removed_fields": [],
"modified_fields": [
{
"name": "description",
"from_value": "Old description",
"to_value": "New description"
}
]
}
}
Response (400 Bad Request):
{
"error": "from version must be < to version"
}
GET /memory/entities/{id}/at?as_of={timestamp}
Query entity state at point in time
Request:
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/memory/entities/e_kubernetes/at?as_of=2025-01-16T00:00:00Z"
Response (200 OK):
{
"entity_id": "e_kubernetes",
"as_of": "2025-01-16T00:00:00Z",
"snapshot": {
"version_num": 1,
"operation": "create",
"snapshot": {...},
"changed_at": "2025-01-15T10:00:00Z",
"changed_by": "[email protected]",
"fields_changed": []
}
}
Response (404 Not Found):
{
"error": "No version of e_kubernetes existed before 2025-01-16T00:00:00Z"
}
Edges
GET /memory/edges/{id}/versions
List all versions of an edge
Request:
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/memory/edges/550e8400-e29b-41d4-a716-446655440000/versions"
Response (200 OK):
{
"edge_id": "550e8400-e29b-41d4-a716-446655440000",
"versions": [
{
"version_num": 2,
"operation": "update",
"snapshot": {...},
"changed_at": "2025-01-30T10:15:00Z",
"changed_by": "[email protected]",
"fields_changed": ["weight"]
}
],
"total": 2
}
GET /memory/edges/{id}/diff?from={v1}&to={v2}
Diff two edge versions
Request:
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/memory/edges/550e8400-e29b-41d4-a716-446655440000/diff?from=1&to=2"
Response (200 OK):
{
"edge_id": "550e8400-e29b-41d4-a716-446655440000",
"diff": {
"from_version": 1,
"to_version": 2,
"added_fields": [],
"removed_fields": [],
"modified_fields": [
{
"name": "weight",
"from_value": 0.5,
"to_value": 0.8
}
]
}
}
Use Cases
Audit Trail
# See who changed what and when
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/memory/entities/e_kubernetes/versions
Rollback
# Get old version
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/memory/entities/e_kubernetes/versions/1 | jq .version.snapshot
# Re-ingest to restore
curl -X POST http://localhost:8080/memory/ingest \
-H "Authorization: Bearer $TOKEN" \
-d '{...snapshot...}'
Time Travel
# See memory as it was 2 weeks ago
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/memory/entities/e_kubernetes/at?as_of=2025-01-16T00:00:00Z"
# Query entire graph as it was then
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/memory/query?query=kubernetes&as_of=2025-01-16T00:00:00Z"
Compliance
# Generate audit report
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/memory/entities/e_kubernetes/versions \
| jq '.versions[] | {changed_at, changed_by, fields_changed}'
Error Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request (invalid query) |
| 401 | Unauthorized (missing/invalid JWT) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Version not found |
| 429 | Rate limit exceeded (200 req/hr per endpoint) |
| 500 | Internal error |
Rate Limits
| Endpoint | Limit |
|---|---|
| /versions | 200/hr |
| /versions/{num} | 200/hr |
| /diff | 100/hr |
| /at | 500/hr |
Timestamps
All timestamps are RFC3339 format (ISO 8601 with timezone):
2025-01-30T10:15:00Z✅2025-01-30T10:15:00+00:00✅2025-01-30T10:15:00❌ (missing timezone)