iatoolkit 2.76.4__tar.gz → 2.76.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iatoolkit-2.76.4/src/iatoolkit.egg-info → iatoolkit-2.76.6}/PKG-INFO +1 -1
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/__init__.py +1 -1
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/core.py +2 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/locales/en.yaml +1 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/locales/es.yaml +1 -0
- iatoolkit-2.76.6/src/iatoolkit/services/signup_guard_service.py +164 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/signup.html +6 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/signup_view.py +30 -14
- {iatoolkit-2.76.4 → iatoolkit-2.76.6/src/iatoolkit.egg-info}/PKG-INFO +1 -1
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit.egg-info/SOURCES.txt +1 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/LICENSE +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/pyproject.toml +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/readme.md +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/setup.cfg +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/access.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/bridge_validation.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/company_paths.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/history_compaction_trigger.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/memory_tools.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/model_registry.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/routes.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/search_terms.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/secret_resolver.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/text_splitter.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/url_safety.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/history_compaction.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/google_auth_client.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/inference_handler.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_proxy.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/advisory_lock.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/api_key_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/bridge_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/memory_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/models.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/runtime_logging.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/api_key_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/attachment_policy_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/auth_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/branding_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/company_context_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/configuration_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/context_builder_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/dispatcher_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/embedding_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/history_compaction_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/history_manager_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/http_tool_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/i18n_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/inference_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/knowledge_base_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/language_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/license_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/llm_client_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/mcp_token_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/memory_compiler_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/memory_question_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/memory_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/memory_sources.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/memory_usage_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/memory_wiki_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/noop_history_compaction_trigger.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/operator_identity_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/contracts.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/parsers/validator.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/pdf_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/prompt_resource_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/prompt_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/query_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/resource_access_scope.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/sql_catalog_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/sql_dataset_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/sql_source_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/storage_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/structured_output_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/system_agent_catalog.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/system_agent_runner.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/system_tools.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/telemetry_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/tool_output_contract.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/tool_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/visual_kb_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/visual_tool_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/warmup_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/web_search/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/web_search_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/images/favicon.ico +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/images/favicon.png +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/images/fernando.jpeg +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_help_content.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_history_button.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_main.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/account.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/chat_public.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/documents.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/landing_page.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/onboarding.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/static/styles/wiki_page.css +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/_chat_header.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/_company_header.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/_login_widget.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/account.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/chat.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/home_hosted_default.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/login_global.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/pdf/base.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/pdf/letter.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/pdf/report.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/pdf/simple.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/templates/wiki_page.html +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/account_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/api_key_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/base_login_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/categories_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/chat_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/configuration_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/connectors_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/embedding_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/help_content_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/history_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/init_context_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/llmquery_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/load_document_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/login_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/logout_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/memory_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/profile_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/prompt_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/rag_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/root_redirect_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/static_page_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/tool_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/users_api_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/views/wiki_page_view.py +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -460,6 +460,7 @@ class IAToolkit:
|
|
|
460
460
|
from iatoolkit.services.sql_source_service import SqlSourceService
|
|
461
461
|
from iatoolkit.services.dispatcher_service import Dispatcher
|
|
462
462
|
from iatoolkit.services.branding_service import BrandingService
|
|
463
|
+
from iatoolkit.services.signup_guard_service import SignupGuardService
|
|
463
464
|
from iatoolkit.services.i18n_service import I18nService
|
|
464
465
|
from iatoolkit.services.language_service import LanguageService
|
|
465
466
|
from iatoolkit.services.configuration_service import ConfigurationService
|
|
@@ -506,6 +507,7 @@ class IAToolkit:
|
|
|
506
507
|
binder.bind(SqlSourceService, to=SqlSourceService)
|
|
507
508
|
binder.bind(Dispatcher, to=Dispatcher)
|
|
508
509
|
binder.bind(BrandingService, to=BrandingService)
|
|
510
|
+
binder.bind(SignupGuardService, to=SignupGuardService)
|
|
509
511
|
binder.bind(I18nService, to=I18nService)
|
|
510
512
|
binder.bind(LanguageService, to=LanguageService)
|
|
511
513
|
# this class can be setup before by iatoolkit enterprise.
|
|
@@ -2859,6 +2859,7 @@ errors:
|
|
|
2859
2859
|
user_already_registered: "The user with email '{email}' already exists in this company."
|
|
2860
2860
|
password_mismatch: "The passwords do not match. Please try again."
|
|
2861
2861
|
signup_not_allowed: "Signup is not allowed for this company. Please contact an administrator."
|
|
2862
|
+
form_expired: "The form has expired. Please try again."
|
|
2862
2863
|
invitation_required: "A valid invitation is required to join this company. Ask your administrator for a new link."
|
|
2863
2864
|
change_password:
|
|
2864
2865
|
token_expired: "The password change link has expired. Please request a new one."
|
|
@@ -2878,6 +2878,7 @@ errors:
|
|
|
2878
2878
|
user_already_registered: "El usuario con email '{email}' ya existe en esta empresa."
|
|
2879
2879
|
password_mismatch: "Las contraseñas no coinciden. Por favor, inténtalo de nuevo."
|
|
2880
2880
|
signup_not_allowed: "El registro no está habilitado para esta empresa. Contacta a un administrador."
|
|
2881
|
+
form_expired: "El formulario expiró. Por favor, inténtalo de nuevo."
|
|
2881
2882
|
invitation_required: "Necesitas una invitación vigente para unirte a esta empresa. Solicita un nuevo enlace al administrador."
|
|
2882
2883
|
change_password:
|
|
2883
2884
|
token_expired: "El enlace de cambio de contraseña ha expirado. Por favor, solicita uno nuevo."
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Product: IAToolkit
|
|
3
|
+
#
|
|
4
|
+
# IAToolkit is open source software.
|
|
5
|
+
|
|
6
|
+
"""Bot detection for the public signup form.
|
|
7
|
+
|
|
8
|
+
Bots fill the signup form with random names and real people's emails, so every
|
|
9
|
+
attempt makes us send a verification email nobody asked for. The checks here run
|
|
10
|
+
before any user is created or any email is sent, and add no step for a person:
|
|
11
|
+
|
|
12
|
+
- a signed form token issued when the page is rendered: a POST without it never
|
|
13
|
+
loaded the page, and one submitted a few seconds after render was not typed;
|
|
14
|
+
- a honeypot field hidden from people, which bots fill in;
|
|
15
|
+
- per-IP and per-email rate limits in Redis.
|
|
16
|
+
|
|
17
|
+
A rejected bot is answered exactly like a successful signup (see SignupView), so
|
|
18
|
+
it cannot learn which check stopped it. Only an expired token is reported, since
|
|
19
|
+
that is a person who left the page open.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import logging
|
|
23
|
+
import os
|
|
24
|
+
import time
|
|
25
|
+
|
|
26
|
+
from itsdangerous import BadSignature, SignatureExpired, URLSafeTimedSerializer
|
|
27
|
+
|
|
28
|
+
from iatoolkit.infra.redis_session_manager import RedisSessionManager
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SignupGuardService:
|
|
32
|
+
FORM_TOKEN_FIELD = 'form_token'
|
|
33
|
+
HONEYPOT_FIELD = 'website'
|
|
34
|
+
|
|
35
|
+
MIN_FILL_SECONDS = 3
|
|
36
|
+
FORM_TOKEN_MAX_AGE_SECONDS = 2 * 60 * 60
|
|
37
|
+
MAX_SIGNUPS_PER_IP = 5
|
|
38
|
+
IP_WINDOW_SECONDS = 60 * 60
|
|
39
|
+
MAX_SIGNUPS_PER_EMAIL = 3
|
|
40
|
+
EMAIL_WINDOW_SECONDS = 24 * 60 * 60
|
|
41
|
+
|
|
42
|
+
# outcomes of check()
|
|
43
|
+
ALLOWED = None
|
|
44
|
+
EXPIRED = 'form_expired'
|
|
45
|
+
|
|
46
|
+
_FORM_TOKEN_SALT = 'signup-form'
|
|
47
|
+
_GMAIL_DOMAINS = {'gmail.com', 'googlemail.com'}
|
|
48
|
+
|
|
49
|
+
def __init__(self):
|
|
50
|
+
self.serializer = URLSafeTimedSerializer(os.getenv("IATOOLKIT_SECRET_KEY"))
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def is_enabled() -> bool:
|
|
54
|
+
# automated end-to-end tests submit the form faster than a person
|
|
55
|
+
return os.getenv('IATOOLKIT_SIGNUP_BOT_GUARD', 'on').strip().lower() not in ('off', 'false', '0')
|
|
56
|
+
|
|
57
|
+
def issue_form_token(self, company_short_name: str) -> str:
|
|
58
|
+
return self.serializer.dumps(company_short_name, salt=self._FORM_TOKEN_SALT)
|
|
59
|
+
|
|
60
|
+
def check(self, company_short_name: str, form, client_ip: str | None, email: str | None) -> str | None:
|
|
61
|
+
"""Return None when the signup may proceed, or the reason it was rejected."""
|
|
62
|
+
if not self.is_enabled():
|
|
63
|
+
return self.ALLOWED
|
|
64
|
+
|
|
65
|
+
reason = self._check_form(company_short_name, form)
|
|
66
|
+
if reason is None:
|
|
67
|
+
reason = self._check_rate_limits(company_short_name, client_ip, email)
|
|
68
|
+
|
|
69
|
+
if reason is not None:
|
|
70
|
+
email_domain = (email or '').rpartition('@')[2].lower() or '-'
|
|
71
|
+
logging.warning(
|
|
72
|
+
"signup rejected: reason=%s company=%s ip=%s email_domain=%s",
|
|
73
|
+
reason, company_short_name, client_ip or '-', email_domain,
|
|
74
|
+
)
|
|
75
|
+
return reason
|
|
76
|
+
|
|
77
|
+
def _check_form(self, company_short_name: str, form) -> str | None:
|
|
78
|
+
if (form.get(self.HONEYPOT_FIELD) or '').strip():
|
|
79
|
+
return 'honeypot'
|
|
80
|
+
|
|
81
|
+
token = form.get(self.FORM_TOKEN_FIELD)
|
|
82
|
+
if not token:
|
|
83
|
+
return 'missing_form_token'
|
|
84
|
+
try:
|
|
85
|
+
token_company, issued_at = self.serializer.loads(
|
|
86
|
+
token,
|
|
87
|
+
salt=self._FORM_TOKEN_SALT,
|
|
88
|
+
max_age=self.FORM_TOKEN_MAX_AGE_SECONDS,
|
|
89
|
+
return_timestamp=True,
|
|
90
|
+
)
|
|
91
|
+
except SignatureExpired:
|
|
92
|
+
return self.EXPIRED
|
|
93
|
+
except BadSignature:
|
|
94
|
+
return 'invalid_form_token'
|
|
95
|
+
|
|
96
|
+
if token_company != company_short_name:
|
|
97
|
+
return 'invalid_form_token'
|
|
98
|
+
if time.time() - issued_at.timestamp() < self.MIN_FILL_SECONDS:
|
|
99
|
+
return 'too_fast'
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
def _check_rate_limits(self, company_short_name: str, client_ip: str | None, email: str | None) -> str | None:
|
|
103
|
+
if client_ip and self._hit(f'signup_guard:ip:{client_ip}', self.IP_WINDOW_SECONDS) > self.MAX_SIGNUPS_PER_IP:
|
|
104
|
+
return 'ip_rate_limit'
|
|
105
|
+
|
|
106
|
+
normalized_email = self.normalize_email(email)
|
|
107
|
+
if normalized_email and self._hit(
|
|
108
|
+
f'signup_guard:email:{normalized_email}', self.EMAIL_WINDOW_SECONDS) > self.MAX_SIGNUPS_PER_EMAIL:
|
|
109
|
+
return 'email_rate_limit'
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
@staticmethod
|
|
113
|
+
def _hit(key: str, window_seconds: int) -> int:
|
|
114
|
+
"""Count one attempt in a fixed window. Fails open: Redis down never blocks a signup."""
|
|
115
|
+
try:
|
|
116
|
+
pipe = RedisSessionManager.pipeline()
|
|
117
|
+
pipe.incr(key)
|
|
118
|
+
pipe.ttl(key)
|
|
119
|
+
count, ttl = pipe.execute()
|
|
120
|
+
if ttl is None or int(ttl) < 0:
|
|
121
|
+
# first hit of the window (or a key left without expiry)
|
|
122
|
+
RedisSessionManager.pipeline().expire(key, window_seconds).execute()
|
|
123
|
+
return int(count)
|
|
124
|
+
except Exception as e:
|
|
125
|
+
logging.warning("signup guard: rate limit unavailable (%s)", e)
|
|
126
|
+
return 0
|
|
127
|
+
|
|
128
|
+
@classmethod
|
|
129
|
+
def normalize_email(cls, email: str | None) -> str:
|
|
130
|
+
"""One key per mailbox: Gmail ignores dots and +tags, so bots vary them."""
|
|
131
|
+
local, _, domain = str(email or '').strip().lower().partition('@')
|
|
132
|
+
if not local or not domain:
|
|
133
|
+
return ''
|
|
134
|
+
local = local.split('+', 1)[0]
|
|
135
|
+
if domain in cls._GMAIL_DOMAINS:
|
|
136
|
+
local = local.replace('.', '')
|
|
137
|
+
domain = 'gmail.com'
|
|
138
|
+
return f'{local}@{domain}'
|
|
139
|
+
|
|
140
|
+
@staticmethod
|
|
141
|
+
def client_ip(request) -> str | None:
|
|
142
|
+
"""The client IP as seen by our own proxy.
|
|
143
|
+
|
|
144
|
+
Behind Cloudflare (Render's edge) the last X-Forwarded-For entry is a
|
|
145
|
+
Cloudflare node shared by many visitors, so CF-Connecting-IP wins: Cloudflare
|
|
146
|
+
always overwrites it with the visitor's address.
|
|
147
|
+
|
|
148
|
+
Otherwise the app sits behind one proxy (the platform router) that appends
|
|
149
|
+
the real client to X-Forwarded-For; anything to its left was sent by the
|
|
150
|
+
client and can be forged. IATOOLKIT_TRUSTED_PROXY_HOPS covers an extra
|
|
151
|
+
proxy in front.
|
|
152
|
+
"""
|
|
153
|
+
cf_ip = request.headers.get('CF-Connecting-IP', '').strip()
|
|
154
|
+
if cf_ip:
|
|
155
|
+
return cf_ip
|
|
156
|
+
|
|
157
|
+
forwarded = [part.strip() for part in request.headers.get('X-Forwarded-For', '').split(',') if part.strip()]
|
|
158
|
+
try:
|
|
159
|
+
hops = max(1, int(os.getenv('IATOOLKIT_TRUSTED_PROXY_HOPS', '1')))
|
|
160
|
+
except ValueError:
|
|
161
|
+
hops = 1
|
|
162
|
+
if forwarded:
|
|
163
|
+
return forwarded[-hops] if len(forwarded) >= hops else forwarded[0]
|
|
164
|
+
return request.remote_addr
|
|
@@ -40,6 +40,12 @@
|
|
|
40
40
|
|
|
41
41
|
<form action="{{ url_for('signup', company_short_name=company_short_name) }}" method="post">
|
|
42
42
|
{% if invite_token %}<input type="hidden" name="invite_token" value="{{ invite_token }}">{% endif %}
|
|
43
|
+
<input type="hidden" name="form_token" value="{{ form_token }}">
|
|
44
|
+
<!-- honeypot: hidden from people, bots fill it in -->
|
|
45
|
+
<div style="position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden;" aria-hidden="true">
|
|
46
|
+
<label for="website">Website</label>
|
|
47
|
+
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off" value="">
|
|
48
|
+
</div>
|
|
43
49
|
<div class="mb-3">
|
|
44
50
|
<label for="email" class="form-label text-secondary">{{ t('ui.signup.email_label') }}</label>
|
|
45
51
|
<input type="email" autocomplete="off" id="email" name="email"
|
|
@@ -8,6 +8,7 @@ from flask import render_template, request, url_for, redirect, flash, make_respo
|
|
|
8
8
|
from iatoolkit.services.profile_service import ProfileService
|
|
9
9
|
from iatoolkit.services.branding_service import BrandingService
|
|
10
10
|
from iatoolkit.services.i18n_service import I18nService
|
|
11
|
+
from iatoolkit.services.signup_guard_service import SignupGuardService
|
|
11
12
|
from injector import inject
|
|
12
13
|
from itsdangerous import URLSafeTimedSerializer
|
|
13
14
|
import os
|
|
@@ -17,10 +18,12 @@ class SignupView(MethodView):
|
|
|
17
18
|
@inject
|
|
18
19
|
def __init__(self, profile_service: ProfileService,
|
|
19
20
|
branding_service: BrandingService,
|
|
20
|
-
i18n_service: I18nService
|
|
21
|
+
i18n_service: I18nService,
|
|
22
|
+
signup_guard_service: SignupGuardService):
|
|
21
23
|
self.profile_service = profile_service
|
|
22
24
|
self.branding_service = branding_service # 3. Guardar la instancia
|
|
23
25
|
self.i18n_service = i18n_service
|
|
26
|
+
self.signup_guard_service = signup_guard_service
|
|
24
27
|
|
|
25
28
|
self.serializer = URLSafeTimedSerializer(os.getenv("IATOOLKIT_SECRET_KEY"))
|
|
26
29
|
|
|
@@ -52,6 +55,7 @@ class SignupView(MethodView):
|
|
|
52
55
|
"company_short_name": company_short_name,
|
|
53
56
|
"branding": branding_data,
|
|
54
57
|
"lang": current_lang,
|
|
58
|
+
"form_token": self.signup_guard_service.issue_form_token(company_short_name),
|
|
55
59
|
}
|
|
56
60
|
if invitation_required or invited_email:
|
|
57
61
|
template_context.update(invite_token=invite_token, invited_email=invited_email)
|
|
@@ -80,19 +84,30 @@ class SignupView(MethodView):
|
|
|
80
84
|
current_lang = request.form.get("lang") or request.args.get("lang")
|
|
81
85
|
invite_token = request.form.get("invite_token") or request.args.get("invite_token")
|
|
82
86
|
|
|
83
|
-
#
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
# bots are stopped before any user is created or any email is sent
|
|
88
|
+
rejection = self.signup_guard_service.check(
|
|
89
|
+
company_short_name, request.form,
|
|
90
|
+
client_ip=self.signup_guard_service.client_ip(request), email=email)
|
|
91
|
+
if rejection == SignupGuardService.EXPIRED:
|
|
92
|
+
response = {"error": self.i18n_service.t('errors.signup.form_expired')}
|
|
93
|
+
elif rejection is not None:
|
|
94
|
+
# answer like a successful signup, so the bot can't tell what stopped it
|
|
95
|
+
flash(self.i18n_service.t('flash_messages.signup_success'), 'success')
|
|
96
|
+
return redirect(url_for('home', company_short_name=company_short_name, lang=current_lang))
|
|
97
|
+
else:
|
|
98
|
+
# create verification token and url for verification
|
|
99
|
+
token = self.serializer.dumps(email, salt='email-confirm')
|
|
100
|
+
verification_url = url_for('verify_account',
|
|
101
|
+
company_short_name=company_short_name,
|
|
102
|
+
token=token, _external=True)
|
|
103
|
+
|
|
104
|
+
response = self.profile_service.signup(
|
|
105
|
+
company_short_name=company_short_name,
|
|
106
|
+
email=email,
|
|
107
|
+
first_name=first_name, last_name=last_name,
|
|
108
|
+
password=password, confirm_password=confirm_password,
|
|
109
|
+
verification_url=verification_url,
|
|
110
|
+
invite_token=invite_token)
|
|
96
111
|
|
|
97
112
|
if "error" in response:
|
|
98
113
|
flash(response["error"], 'error')
|
|
@@ -100,6 +115,7 @@ class SignupView(MethodView):
|
|
|
100
115
|
"company_short_name": company_short_name,
|
|
101
116
|
"branding": branding_data,
|
|
102
117
|
"lang": current_lang,
|
|
118
|
+
"form_token": self.signup_guard_service.issue_form_token(company_short_name),
|
|
103
119
|
"form_data": {
|
|
104
120
|
"first_name": first_name,
|
|
105
121
|
"last_name": last_name,
|
|
@@ -161,6 +161,7 @@ src/iatoolkit/services/prompt_resource_service.py
|
|
|
161
161
|
src/iatoolkit/services/prompt_service.py
|
|
162
162
|
src/iatoolkit/services/query_service.py
|
|
163
163
|
src/iatoolkit/services/resource_access_scope.py
|
|
164
|
+
src/iatoolkit/services/signup_guard_service.py
|
|
164
165
|
src/iatoolkit/services/signup_policy_resolver.py
|
|
165
166
|
src/iatoolkit/services/sql_catalog_service.py
|
|
166
167
|
src/iatoolkit/services/sql_dataset_service.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/history_compaction_trigger.py
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py
RENAMED
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/signup_policy_resolver.py
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/common/interfaces/web_search_provider.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/history_compaction.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_compiler.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_correction.prompt
RENAMED
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/core_identity.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/email_output.prompt
RENAMED
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/format_styles.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/html_structures.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/links_documents.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/memory_usage.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/output_basics.prompt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_casting.prompt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/file_connector_factory.py
RENAMED
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/google_drive_connector.py
RENAMED
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/connectors/local_file_connector.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iatoolkit-2.76.4 → iatoolkit-2.76.6}/src/iatoolkit/repositories/filesystem_asset_repository.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|