Add events and relationships API (Phase 1: flesh out the graph)

Events (create/list-per-person/soft-delete) and relationships (create/list-per-person/soft-delete) through the layered stack: editor-gated writes, privacy-engine reads, audit on every change. Events carry exactly one subject (person XOR partnership); relationships are typed qualified edges (parent_child gets a biological/adoptive/step/foster/donor/guardian qualifier). Adds a single-person GET. 18 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Justin Paul <justin@jpaul.me>
This commit is contained in:
2026-06-06 12:10:56 -04:00
parent a799d101b5
commit d6e2df4a61
10 changed files with 570 additions and 2 deletions
+39
View File
@@ -0,0 +1,39 @@
import uuid
from datetime import date, datetime
from pydantic import BaseModel, ConfigDict
class EventCreate(BaseModel):
event_type: str
# Exactly one subject: a person or a partnership (relationship).
person_id: uuid.UUID | None = None
relationship_id: uuid.UUID | None = None
place_id: uuid.UUID | None = None
# Verbatim date string (e.g. "ABT 1850") and/or a normalized range.
date_value: str | None = None
date_start: date | None = None
date_end: date | None = None
date_precision: str | None = None
calendar: str = "gregorian"
detail: str | None = None
notes: str | None = None
class EventRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
tree_id: uuid.UUID
event_type: str
person_id: uuid.UUID | None
relationship_id: uuid.UUID | None
place_id: uuid.UUID | None
date_value: str | None
date_start: date | None
date_end: date | None
date_precision: str | None
calendar: str
detail: str | None
notes: str | None
created_at: datetime
+28
View File
@@ -0,0 +1,28 @@
import uuid
from datetime import datetime
from pydantic import BaseModel, ConfigDict
from app.models.enums import ParentChildQualifier, RelationshipType
class RelationshipCreate(BaseModel):
type: RelationshipType
person_from_id: uuid.UUID
person_to_id: uuid.UUID
# Only meaningful for parent_child edges (from = parent, to = child).
qualifier: ParentChildQualifier | None = None
notes: str | None = None
class RelationshipRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
tree_id: uuid.UUID
type: RelationshipType
person_from_id: uuid.UUID
person_to_id: uuid.UUID
qualifier: ParentChildQualifier | None
notes: str | None
created_at: datetime