feat(phase7): implement versioning, ranking, rebuild + cleanup tasks folder
- 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).
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
# 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**:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
http://localhost:8080/memory/entities/e_kubernetes/versions
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```json
|
||||
{
|
||||
"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**:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
http://localhost:8080/memory/entities/e_kubernetes/versions/2
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```json
|
||||
{
|
||||
"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):
|
||||
```json
|
||||
{
|
||||
"error": "Version 99 not found for entity e_kubernetes"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET /memory/entities/{id}/diff?from={v1}&to={v2}
|
||||
Diff two versions
|
||||
|
||||
**Request**:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
"http://localhost:8080/memory/entities/e_kubernetes/diff?from=1&to=3"
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```json
|
||||
{
|
||||
"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):
|
||||
```json
|
||||
{
|
||||
"error": "from version must be < to version"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET /memory/entities/{id}/at?as_of={timestamp}
|
||||
Query entity state at point in time
|
||||
|
||||
**Request**:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
"http://localhost:8080/memory/entities/e_kubernetes/at?as_of=2025-01-16T00:00:00Z"
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```json
|
||||
{
|
||||
"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):
|
||||
```json
|
||||
{
|
||||
"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**:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
"http://localhost:8080/memory/edges/550e8400-e29b-41d4-a716-446655440000/versions"
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```json
|
||||
{
|
||||
"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**:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
"http://localhost:8080/memory/edges/550e8400-e29b-41d4-a716-446655440000/diff?from=1&to=2"
|
||||
```
|
||||
|
||||
**Response** (200 OK):
|
||||
```json
|
||||
{
|
||||
"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
|
||||
```bash
|
||||
# See who changed what and when
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
http://localhost:8080/memory/entities/e_kubernetes/versions
|
||||
```
|
||||
|
||||
### Rollback
|
||||
```bash
|
||||
# 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
|
||||
```bash
|
||||
# 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
|
||||
```bash
|
||||
# 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)
|
||||
Reference in New Issue
Block a user