Self-hosted knowledge management for SMEs: a split-screen Markdown editor whose sections an LLM refines while you write, and RAG question answering over the documents that result. FastAPI + Postgres/pgvector on the back, SvelteKit on the front, everything OpenAI-compatible and self-hostable. Squashed into a single commit; the development history stays local. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CA43ZJda8Rbp2hKXNy8f6b
41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
"""The document audit trail.
|
|
|
|
Every content edit and lifecycle transition is appended to `document_events`
|
|
as an immutable record of who did what, when. Content-bearing actions snapshot
|
|
the Markdown source of truth (never the disposable chunks) so a past version
|
|
can later be viewed or diffed.
|
|
"""
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models import Document, DocumentEvent, DocumentEventAction, User
|
|
|
|
|
|
def record_event(
|
|
db: AsyncSession,
|
|
document: Document,
|
|
actor: User,
|
|
action: DocumentEventAction,
|
|
*,
|
|
snapshot: bool = False,
|
|
) -> None:
|
|
"""Append an audit record for `document`.
|
|
|
|
`snapshot` freezes the current Markdown, title and meta so the version can
|
|
be reconstructed later — pass it for content-bearing events (created /
|
|
edited). Visibility is small, so it is always recorded. Leave `snapshot`
|
|
False for pure transitions that carry no new content. The document must
|
|
already have an id (flush a freshly created document first).
|
|
"""
|
|
db.add(
|
|
DocumentEvent(
|
|
document_id=document.id,
|
|
actor_id=actor.id,
|
|
action=action,
|
|
content_md=document.content_md if snapshot else None,
|
|
title=document.title if snapshot else None,
|
|
visibility=document.visibility,
|
|
meta=document.meta if snapshot else None,
|
|
)
|
|
)
|