generated from coulomb/repo-seed
relationship persistence, context entities, idempotent asset creation, audit/version handling for relationship changes
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from .actors import Actor, ActorType, OperationContext
|
||||
from .assets import AssetRepresentation, KnowledgeAsset, RepresentationKind
|
||||
from .audit import AuditEvent, AuditOutcome
|
||||
from .idempotency import IdempotencyRecord, IdempotencyStatus
|
||||
from .metadata import Classification, LifecycleState, MetadataRecord, Sensitivity
|
||||
from .policy import PolicyDecision, PolicyEffect
|
||||
from .primitives import content_digest, mapping_digest, new_id, stable_json_dumps, utc_now
|
||||
@@ -31,6 +32,8 @@ __all__ = [
|
||||
"ContextEntityType",
|
||||
"CoreRelationship",
|
||||
"DerivedArtifactLineage",
|
||||
"IdempotencyRecord",
|
||||
"IdempotencyStatus",
|
||||
"KnowledgeAsset",
|
||||
"LifecycleState",
|
||||
"MetadataRecord",
|
||||
@@ -48,4 +51,3 @@ __all__ = [
|
||||
"stable_json_dumps",
|
||||
"utc_now",
|
||||
]
|
||||
|
||||
|
||||
48
src/kontextual_engine/core/idempotency.py
Normal file
48
src/kontextual_engine/core/idempotency.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""Idempotency records for mutation safety."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
from .primitives import compact_dict, utc_now
|
||||
|
||||
|
||||
class IdempotencyStatus(str, Enum):
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class IdempotencyRecord:
|
||||
key: str
|
||||
operation: str
|
||||
request_hash: str
|
||||
result_refs: dict[str, Any]
|
||||
status: IdempotencyStatus = IdempotencyStatus.COMPLETED
|
||||
created_at: str = field(default_factory=lambda: utc_now().isoformat())
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
return compact_dict(
|
||||
{
|
||||
"key": self.key,
|
||||
"operation": self.operation,
|
||||
"request_hash": self.request_hash,
|
||||
"result_refs": dict(self.result_refs),
|
||||
"status": self.status.value,
|
||||
"created_at": self.created_at,
|
||||
}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> "IdempotencyRecord":
|
||||
return cls(
|
||||
key=data["key"],
|
||||
operation=data["operation"],
|
||||
request_hash=data["request_hash"],
|
||||
result_refs=dict(data.get("result_refs", {})),
|
||||
status=IdempotencyStatus(data.get("status", IdempotencyStatus.COMPLETED.value)),
|
||||
created_at=data["created_at"],
|
||||
)
|
||||
|
||||
@@ -41,6 +41,16 @@ class ContextEntity:
|
||||
}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> "ContextEntity":
|
||||
return cls(
|
||||
entity_id=data["entity_id"],
|
||||
entity_type=ContextEntityType(data["entity_type"]),
|
||||
name=data["name"],
|
||||
external_ref=data.get("external_ref"),
|
||||
metadata=dict(data.get("metadata", {})),
|
||||
)
|
||||
|
||||
|
||||
class RelationshipTargetKind(str, Enum):
|
||||
ASSET = "asset"
|
||||
@@ -80,3 +90,19 @@ class CoreRelationship:
|
||||
}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> "CoreRelationship":
|
||||
return cls(
|
||||
relationship_id=data["relationship_id"],
|
||||
source_id=data["source_id"],
|
||||
target_id=data["target_id"],
|
||||
predicate=data["predicate"],
|
||||
target_kind=RelationshipTargetKind(data.get("target_kind", RelationshipTargetKind.ASSET.value)),
|
||||
direction=data.get("direction", "outbound"),
|
||||
confidence=data.get("confidence"),
|
||||
valid_from=data.get("valid_from"),
|
||||
valid_to=data.get("valid_to"),
|
||||
actor_id=data.get("actor_id"),
|
||||
provenance=dict(data.get("provenance", {})),
|
||||
created_at=data["created_at"],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user