296 lines
5.6 KiB
Markdown
296 lines
5.6 KiB
Markdown
# 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)
|