Initial curated RAGcore source from c16667f0c9397e2bfc8dd0255b114fba23c8d05e
This commit is contained in:
commit
7ca726caf2
659 files changed
+98171
No files matched your search
@@ -0,0 +1,143 @@
|
||||
"""PostgreSQL integration coverage for append-only audit events."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime
|
||||
from typing import cast
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.exc import DBAPIError
|
||||
|
||||
from ragcore.application.audit import AuditEventService
|
||||
from ragcore.config import Settings
|
||||
from ragcore.domain.audit import AuditEvent, AuditEventType
|
||||
from ragcore.domain.control import Workspace
|
||||
from ragcore.infrastructure.database import (
|
||||
create_database_engine,
|
||||
create_session_factory,
|
||||
session_scope,
|
||||
)
|
||||
from ragcore.infrastructure.database.audit import AuditEventRepository
|
||||
from ragcore.infrastructure.database.control import ControlPlaneRepository
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def audit_context() -> tuple[AuditEventRepository, Workspace, Workspace]:
|
||||
engine = create_database_engine(Settings(env="test"))
|
||||
factory = create_session_factory(engine)
|
||||
async with session_scope(factory) as session:
|
||||
suffix = uuid4().hex[:8]
|
||||
first = Workspace(uuid4(), "First", f"first-{suffix}")
|
||||
second = Workspace(uuid4(), "Second", f"second-{suffix}")
|
||||
control = ControlPlaneRepository(session)
|
||||
await control.create_workspace(first)
|
||||
await control.create_workspace(second)
|
||||
await session.commit()
|
||||
yield AuditEventRepository(session), first, second
|
||||
await session.rollback()
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_audit_events_redact_content_and_preserve_trace_correlation(
|
||||
audit_context: tuple[AuditEventRepository, Workspace, Workspace],
|
||||
) -> None:
|
||||
repository, workspace, _ = audit_context
|
||||
service = AuditEventService(repository, clock=lambda: datetime(2026, 8, 1, tzinfo=UTC))
|
||||
event = await service.record(
|
||||
workspace_id=workspace.id,
|
||||
event_type=AuditEventType.SECURITY_FAILURE,
|
||||
trace_id="trace-123",
|
||||
correlation_id="request-456",
|
||||
details={
|
||||
"reason": "denied",
|
||||
"token": "rc_sa_secret",
|
||||
"query": "private text",
|
||||
"nested": {"password": "secret", "safe": "kept"},
|
||||
},
|
||||
)
|
||||
await repository._session.commit()
|
||||
|
||||
stored = await service.list_events(workspace.id)
|
||||
assert event.trace_id == "trace-123"
|
||||
assert stored[0].correlation_id == "request-456"
|
||||
assert stored[0].details == {"reason": "denied", "nested": {"safe": "kept"}}
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_repository_resanitizes_mutated_event_details(
|
||||
audit_context: tuple[AuditEventRepository, Workspace, Workspace],
|
||||
) -> None:
|
||||
repository, workspace, _ = audit_context
|
||||
event = AuditEvent(
|
||||
id=uuid4(),
|
||||
workspace_id=workspace.id,
|
||||
event_type=AuditEventType.ADMIN_ACTION,
|
||||
occurred_at=datetime.now(UTC),
|
||||
trace_id="mutable-details",
|
||||
details={"nested": {}},
|
||||
)
|
||||
nested = cast(dict[str, object], event.details["nested"])
|
||||
nested["token"] = "must-not-persist"
|
||||
|
||||
await repository.append(event)
|
||||
await repository._session.commit()
|
||||
|
||||
stored = await repository.list_events(workspace.id)
|
||||
assert stored[0].details == {"nested": {}}
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_audit_reads_are_workspace_scoped(
|
||||
audit_context: tuple[AuditEventRepository, Workspace, Workspace],
|
||||
) -> None:
|
||||
repository, first, second = audit_context
|
||||
service = AuditEventService(repository)
|
||||
await service.record(
|
||||
workspace_id=first.id,
|
||||
event_type=AuditEventType.ADMIN_ACTION,
|
||||
trace_id="first-trace",
|
||||
)
|
||||
await service.record(
|
||||
workspace_id=second.id,
|
||||
event_type=AuditEventType.ADMIN_ACTION,
|
||||
trace_id="second-trace",
|
||||
)
|
||||
await repository._session.commit()
|
||||
|
||||
assert [event.trace_id for event in await service.list_events(first.id)] == ["first-trace"]
|
||||
assert [event.trace_id for event in await service.list_events(second.id)] == ["second-trace"]
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_database_rejects_audit_update_delete_and_truncate(
|
||||
audit_context: tuple[AuditEventRepository, Workspace, Workspace],
|
||||
) -> None:
|
||||
repository, workspace, _ = audit_context
|
||||
service = AuditEventService(repository)
|
||||
event = await service.record(
|
||||
workspace_id=workspace.id,
|
||||
event_type=AuditEventType.ADMIN_ACTION,
|
||||
trace_id="immutable-trace",
|
||||
)
|
||||
await repository._session.commit()
|
||||
|
||||
with pytest.raises(DBAPIError, match="append-only"):
|
||||
await repository._session.execute(
|
||||
text("UPDATE audit.audit_events SET trace_id = 'changed' WHERE id = :id"),
|
||||
{"id": event.id},
|
||||
)
|
||||
await repository._session.rollback()
|
||||
with pytest.raises(DBAPIError, match="append-only"):
|
||||
await repository._session.execute(
|
||||
text("DELETE FROM audit.audit_events WHERE id = :id"), {"id": event.id}
|
||||
)
|
||||
await repository._session.rollback()
|
||||
with pytest.raises(DBAPIError, match="append-only"):
|
||||
await repository._session.execute(text("TRUNCATE audit.audit_events"))
|
||||
await repository._session.rollback()
|
||||
|
||||
assert (await service.list_events(workspace.id))[0].trace_id == "immutable-trace"
|
||||
Reference in new issue
Block a user