refactor(topology): introduce TopologyRepository protocol with DTO return types

Replace repo: BaseRepository with a structural TopologyRepository protocol
in persistence.py and allocator.py. All read methods now return typed DTOs
(TopologySummary, LANRow, DeckyRow, EdgeRow) instead of raw dicts, eliminating
silent field-shape regressions across the topology subsystem.

TopologySummary gains email_personas and language_default so api_personas.py
can continue reading those fields via attribute access. hydrate() converts
DTOs to dicts before passing to _backfill_decky_configs, keeping the mutable
working-state function dict-based at its boundary. All production callers
(router handlers, mutator, CLI, heartbeat) migrated from dict/get access to
attribute access. 134 tests pass.
This commit is contained in:
2026-04-30 23:51:41 -04:00
parent 3456d3ab45
commit fc1f0914b7
34 changed files with 231 additions and 175 deletions

View File

@@ -6,6 +6,7 @@ from typing import Any, Optional
from sqlalchemy import asc, select, text, update
from decnet.web.db.models import LAN, TopologyEdge
from decnet.web.db.models.topology import LANRow
class LansMixin:
@@ -117,9 +118,9 @@ class LansMixin:
async def list_lans_for_topology(
self, topology_id: str
) -> list[dict[str, Any]]:
) -> list[LANRow]:
async with self._session() as session:
result = await session.execute(
select(LAN).where(LAN.topology_id == topology_id).order_by(asc(LAN.name))
)
return [r.model_dump(mode="json") for r in result.scalars().all()]
return [LANRow.model_validate(r.model_dump(mode="json")) for r in result.scalars().all()]