Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
31 lines
1.5 KiB
Python
31 lines
1.5 KiB
Python
import uuid
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import ForeignKey, String
|
||
from sqlalchemy.dialects.postgresql import JSONB, TIMESTAMP, UUID
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from app.db.base import Base
|
||
|
||
|
||
class Historie(Base):
|
||
"""Prompt 13: vollständige Audit-Protokollierung ist Sprint 5. Hier bereits
|
||
angelegt, weil Sprint 3 (Objekt-Übernahme, Prompt 02.8) einen ersten
|
||
Ereignistyp braucht – append-only, kein Update/Delete durch die Anwendung."""
|
||
|
||
__tablename__ = "historie"
|
||
|
||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||
erzeugt_von_server_id: Mapped[int] = mapped_column(ForeignKey("systemknoten.id"), nullable=False)
|
||
zeitpunkt: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), nullable=False)
|
||
benutzer_id: Mapped[int | None] = mapped_column(ForeignKey("benutzer.id"))
|
||
ereignistyp: Mapped[str] = mapped_column(String, nullable=False)
|
||
entitaet_typ: Mapped[str] = mapped_column(String, nullable=False)
|
||
entitaet_id: Mapped[str] = mapped_column(String, nullable=False)
|
||
alter_wert: Mapped[dict | None] = mapped_column(JSONB)
|
||
neuer_wert: Mapped[dict | None] = mapped_column(JSONB)
|
||
begruendung: Mapped[str | None] = mapped_column(String)
|
||
# FILE-008: SHA-256 über Inhalt+Vorgänger-Hash, Kette läuft je
|
||
# (entitaet_typ, entitaet_id) separat - siehe app/services/historie_hash.py.
|
||
hash: Mapped[str] = mapped_column(String, nullable=False)
|