feat: honor temporal read context

This commit is contained in:
2026-08-05 00:03:32 +02:00
parent 7aa1e53ed2
commit 6144fba6ce
4 changed files with 53 additions and 16 deletions
+2 -1
View File
@@ -117,7 +117,8 @@ manifest = ModuleManifest(
summary="Define and resolve effective authority, jurisdiction, legal basis, and evidence.",
body=(
"Mandates stores immutable revisions and resolves the one effective authority for a task. "
"Conflicting or missing authority fails closed. Consequential consumers retain the exact revision and evidence."
"Conflicting or missing authority fails closed. Consequential consumers retain the exact revision and evidence. "
"Catalogue reads follow the titlebar valid-time and recorded-time selection; explicit resolution times take precedence and current authorization is unchanged."
),
layer="configured",
documentation_types=("admin", "user"),
+16 -15
View File
@@ -3,7 +3,6 @@ from __future__ import annotations
from datetime import UTC, datetime
from typing import Any, Mapping
from sqlalchemy import or_
from sqlalchemy.orm import Session
from govoplan_core.core.institutional import (
@@ -15,6 +14,8 @@ from govoplan_core.core.institutional import (
resolve_mandate_candidates,
revise_mandate_definition,
)
from govoplan_core.core.temporal import TemporalDataContext
from govoplan_core.db.temporal import apply_temporal_revision_filter
from govoplan_mandates.backend.db.models import MandateRevision
@@ -120,7 +121,7 @@ def get_mandate(
if revision is not None:
query = query.filter(MandateRevision.revision == revision)
else:
query = query.filter(MandateRevision.superseded_at.is_(None))
query = apply_temporal_revision_filter(query, MandateRevision)
row = query.order_by(MandateRevision.recorded_at.desc()).first()
return _definition_from_row(row) if row is not None else None
@@ -137,8 +138,8 @@ def list_mandates(
raise MandateStoreError("Mandate list limit must be between 1 and 200.")
query = session.query(MandateRevision).filter(
MandateRevision.tenant_id == tenant_id,
MandateRevision.superseded_at.is_(None),
)
query = apply_temporal_revision_filter(query, MandateRevision)
if status:
query = query.filter(MandateRevision.status == status)
rows = query.order_by(
@@ -162,19 +163,19 @@ class SqlMandateResolver:
"Mandate resolution cannot cross tenants."
)
typed_session = _session(session)
query = typed_session.query(MandateRevision).filter(
MandateRevision.tenant_id == tenant_id,
)
query = apply_temporal_revision_filter(
query,
MandateRevision,
context=TemporalDataContext(
validity_mode="at",
valid_at=request.effective_at,
),
)
rows = (
typed_session.query(MandateRevision)
.filter(
MandateRevision.tenant_id == tenant_id,
or_(
MandateRevision.valid_from.is_(None),
MandateRevision.valid_from <= request.effective_at,
),
or_(
MandateRevision.valid_to.is_(None),
MandateRevision.valid_to > request.effective_at,
),
)
query
.order_by(
MandateRevision.mandate_id.asc(),
MandateRevision.recorded_at.desc(),