Repository: All-Hands-AI/OpenHands
File: openhands/app_server/app_conversation/live_status_app_conversation_service.py (Python)

Code before:
        return agent_server_url

    async def _validate_and_get_parent_conversation(
        self, parent_conversation_id: UUID, user_id: str | None = None
    ) -> AppConversationInfo:
        """Validate and retrieve parent conversation info.

        Args:
            parent_conversation_id: The ID of the parent conversation to validate
            user_id: The ID of the current user for security validation

        Returns:
            The parent conversation info if valid

        Raises:
            ValueError: If parent conversation not found or access denied
        """
        parent_info = (
            await self.app_conversation_info_service.get_app_conversation_info(
                parent_conversation_id
            )
        )
        if parent_info is None:
            raise ValueError(f'Parent conversation not found: {parent_conversation_id}')
        # Security check: ensure parent conversation belongs to same user
        if parent_info.created_by_user_id != user_id:
            raise ValueError(
                f'Access denied: parent conversation {parent_conversation_id} does not belong to current user'
            )
        return parent_info

    def _inherit_configuration_from_parent(
        self, request: AppConversationStartRequest, parent_info: AppConversationInfo
    ) -> None:
        """Inherit configuration from parent conversation if not explicitly provided.

        This ensures sub-conversations automatically inherit:
        - Sandbox ID (to share the same workspace/environment)
        - Git parameters (repository, branch, provider)
        - LLM model

        Args:
            request: The conversation start request to modify
            parent_info: The parent conversation info to inherit from
        """
        # Inherit sandbox_id from parent to share the same workspace/environment
        if not request.sandbox_id:
            request.sandbox_id = parent_info.sandbox_id

        # Inherit git parameters from parent if not provided
        if not request.selected_repository:

Review comment (security):
Is this necessary here, in `openhands/app_server/app_conversation/live_status_app_conversation_service.py` ?

It seems to me that authorization code should happen before it gets here. Hopefully in the creation/validation of the request, that is, somewhere in or where `UserContext` is injected

Code after:
        assert exposed_urls is not None
        agent_server_url = next(
            exposed_url.url
            for exposed_url in exposed_urls
            if exposed_url.name == AGENT_SERVER
        )
        return agent_server_url

    def _inherit_configuration_from_parent(
        self, request: AppConversationStartRequest, parent_info: AppConversationInfo
    ) -> None:
        """Inherit configuration from parent conversation if not explicitly provided.

        This ensures sub-conversations automatically inherit:
        - Sandbox ID (to share the same workspace/environment)
        - Git parameters (repository, branch, provider)
        - LLM model

        Args:
            request: The conversation start request to modify
            parent_info: The parent conversation info to inherit from
        """
        # Inherit sandbox_id from parent to share the same workspace/environment
        if not request.sandbox_id:
            request.sandbox_id = parent_info.sandbox_id

        # Inherit git parameters from parent if not provided
        if not request.selected_repository:
            request.selected_repository = parent_info.selected_repository
        if not request.selected_branch:
            request.selected_branch = parent_info.selected_branch
        if not request.git_provider:
            request.git_provider = parent_info.git_provider

        # Inherit LLM model from parent if not provided
        if not request.llm_model and parent_info.llm_model:
            request.llm_model = parent_info.llm_model

    async def _build_start_conversation_request_for_user(
        self,
        initial_message: SendMessageRequest | None,
        git_provider: ProviderType | None,
        working_dir: str,
        agent_type: AgentType = AgentType.DEFAULT,
        llm_model: str | None = None,
    ) -> StartConversationRequest:
        user = await self.user_context.get_user_info()

        # Set up a secret for the git token
        secrets = await self.user_context.get_secrets()
        if git_provider: