diff --git a/backend/src/core/config/static/database/system_agents.yaml b/backend/src/core/config/static/database/system_agents.yaml index 36f52f6..3d3b0be 100644 --- a/backend/src/core/config/static/database/system_agents.yaml +++ b/backend/src/core/config/static/database/system_agents.yaml @@ -25,3 +25,7 @@ agents: - calendar - contacts - memory + allowed_commands: + - calendar + - contacts + - memory diff --git a/backend/src/v1/auth/dev_phone_session.py b/backend/src/v1/auth/dev_phone_session.py index 0c9a4a6..b1365a5 100644 --- a/backend/src/v1/auth/dev_phone_session.py +++ b/backend/src/v1/auth/dev_phone_session.py @@ -24,13 +24,7 @@ async def create_dev_phone_session( *, request: PhoneSessionCreateRequest, ) -> SessionResponse: - user_id = await _find_user_id_by_phone(request.phone) - if user_id is None: - raise _auth_error( - status_code=401, - code="AUTH_USER_NOT_FOUND", - detail="User not found", - ) + user_id = await _find_or_create_user_by_phone(request.phone) token = _sign_access_token(sub=str(user_id)) return SessionResponse( @@ -42,6 +36,46 @@ async def create_dev_phone_session( ) +async def _find_or_create_user_by_phone(phone: str) -> UUID: + admin_client = supabase_service.get_admin_client() + users = await asyncio.to_thread( + _list_users_with_phone, admin_client, phone + ) + if users: + raw_id = str(getattr(users[0], "id", "")) + if raw_id: + return UUID(raw_id) + + return await _create_dev_user(admin_client, phone) + + +async def _create_dev_user(admin_client: Any, phone: str) -> UUID: + try: + user = await asyncio.to_thread( + admin_client.auth.admin.create_user, + { + "phone": phone, + "phone_confirm": True, + }, + ) + raw_id = str(getattr(user, "id", "")) + if not raw_id: + raise _auth_error( + status_code=500, + code="AUTH_USER_CREATE_FAILED", + detail="Failed to create dev user", + ) + logger.info("Created dev user", phone=phone, user_id=raw_id) + return UUID(raw_id) + except Exception as exc: + logger.error("Failed to create dev user", error=str(exc)) + raise _auth_error( + status_code=500, + code="AUTH_USER_CREATE_FAILED", + detail="Failed to create dev user", + ) from exc + + async def _find_user_id_by_phone(phone: str) -> UUID | None: admin_client = supabase_service.get_admin_client() users = await asyncio.to_thread( diff --git a/backend/src/v1/auth/gateway.py b/backend/src/v1/auth/gateway.py index 9a3cb02..2f2553c 100644 --- a/backend/src/v1/auth/gateway.py +++ b/backend/src/v1/auth/gateway.py @@ -52,6 +52,10 @@ class SupabaseAuthGateway(AuthServiceGateway): return supabase_service.get_admin_client() async def send_otp(self, request: OtpSendRequest) -> None: + if config.runtime.environment == "dev": + logger.info("Skipping OTP send in dev environment", phone=request.phone) + return + client = self._get_client() payload: dict[str, Any] = { "phone": request.phone,