ref #10: [fix] enforce UUID chat ids

Normalize chat ids to a single UUID form so locks, repository keys, and mount paths cannot diverge through path-like aliases.
This commit is contained in:
Azamat 2026-04-02 22:35:50 +03:00
parent 44f1549d80
commit e629e34c4d
7 changed files with 192 additions and 80 deletions

View file

@ -1,6 +1,6 @@
from dataclasses import dataclass
from datetime import timedelta
from uuid import uuid4
from uuid import UUID, uuid4
from domain.sandbox import SandboxSession
from usecase.interface import (
@ -35,15 +35,17 @@ class CreateSandbox:
self._ttl = ttl
def execute(self, command: CreateSandboxCommand) -> SandboxSession:
with self._locker.lock(command.chat_id):
session = self._repository.get_active_by_chat_id(command.chat_id)
chat_id = _canonical_chat_id(command.chat_id)
with self._locker.lock(chat_id):
session = self._repository.get_active_by_chat_id(chat_id)
now = self._clock.now()
if session is not None and session.expires_at > now:
self._logger.info(
'sandbox_reused',
attrs={
'chat_id': command.chat_id,
'chat_id': chat_id,
'session_id': session.session_id,
'container_id': session.container_id,
},
@ -54,7 +56,7 @@ class CreateSandbox:
self._logger.info(
'sandbox_replaced',
attrs={
'chat_id': command.chat_id,
'chat_id': chat_id,
'session_id': session.session_id,
'container_id': session.container_id,
},
@ -66,7 +68,7 @@ class CreateSandbox:
expires_at = created_at + self._ttl
new_session = self._runtime.create(
session_id=_new_session_id(),
chat_id=command.chat_id,
chat_id=chat_id,
created_at=created_at,
expires_at=expires_at,
)
@ -74,7 +76,7 @@ class CreateSandbox:
self._logger.info(
'sandbox_created',
attrs={
'chat_id': command.chat_id,
'chat_id': chat_id,
'session_id': new_session.session_id,
'container_id': new_session.container_id,
},
@ -151,3 +153,7 @@ class CleanupExpiredSandboxes:
def _new_session_id() -> str:
return uuid4().hex
def _canonical_chat_id(chat_id: str) -> str:
return str(UUID(str(chat_id).strip()))