iatoolkit 2.72.1__tar.gz → 2.72.2__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.
Files changed (279) hide show
  1. {iatoolkit-2.72.1/src/iatoolkit.egg-info → iatoolkit-2.72.2}/PKG-INFO +1 -1
  2. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/access.py +32 -0
  4. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/company_context_service.py +17 -3
  5. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/context_builder_service.py +5 -1
  6. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/knowledge_base_service.py +5 -1
  7. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/query_service.py +19 -0
  8. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/resource_access_scope.py +42 -0
  9. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/user_session_context_service.py +12 -0
  10. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/rag_api_view.py +55 -2
  11. {iatoolkit-2.72.1 → iatoolkit-2.72.2/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  12. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/LICENSE +0 -0
  13. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/LICENSE_COMMUNITY.md +0 -0
  14. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/pyproject.toml +0 -0
  15. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/readme.md +0 -0
  16. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/setup.cfg +0 -0
  17. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/base_company.py +0 -0
  18. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/cli_commands.py +0 -0
  19. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/__init__.py +0 -0
  20. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/bridge_validation.py +0 -0
  21. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/company_paths.py +0 -0
  22. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/exceptions.py +0 -0
  23. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  24. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  25. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  26. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  27. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  28. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  29. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  30. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/memory_tools.py +0 -0
  31. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/model_registry.py +0 -0
  32. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/routes.py +0 -0
  33. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/search_terms.py +0 -0
  34. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/secret_resolver.py +0 -0
  35. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/session_manager.py +0 -0
  36. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/text_splitter.py +0 -0
  37. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/url_safety.py +0 -0
  38. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/common/util.py +0 -0
  39. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/company_registry.py +0 -0
  40. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/__init__.py +0 -0
  41. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  42. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
  43. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
  44. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
  45. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
  46. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
  47. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
  48. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
  49. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  50. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  51. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  52. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  53. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  54. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  55. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  56. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  57. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  58. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  59. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  60. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  61. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  62. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  63. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  64. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  65. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  66. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  67. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  68. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  69. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  70. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  71. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  72. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  73. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  74. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  75. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  76. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  77. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/core.py +0 -0
  78. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/__init__.py +0 -0
  79. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  80. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/call_service.py +0 -0
  81. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  82. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  83. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  84. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  85. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  86. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  87. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  88. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/google_auth_client.py +0 -0
  89. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/google_chat_app.py +0 -0
  90. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  91. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/inference_handler.py +0 -0
  92. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  93. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  94. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  95. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  96. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  97. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  98. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  99. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  100. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  101. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_proxy.py +0 -0
  102. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/llm_response.py +0 -0
  103. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  104. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/locales/en.yaml +0 -0
  105. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/locales/es.yaml +0 -0
  106. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/__init__.py +0 -0
  107. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/advisory_lock.py +0 -0
  108. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  109. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/bridge_repo.py +0 -0
  110. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/database_manager.py +0 -0
  111. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/document_repo.py +0 -0
  112. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  113. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  114. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  115. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  116. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  117. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
  118. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/memory_repo.py +0 -0
  119. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
  120. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/models.py +0 -0
  121. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/profile_repo.py +0 -0
  122. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  123. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  124. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  125. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/repositories/vs_repo.py +0 -0
  126. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/runtime_logging.py +0 -0
  127. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/__init__.py +0 -0
  128. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/api_key_service.py +0 -0
  129. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  130. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/auth_service.py +0 -0
  131. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/branding_service.py +0 -0
  132. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/configuration_service.py +0 -0
  133. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/dispatcher_service.py +0 -0
  134. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/embedding_service.py +0 -0
  135. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/excel_service.py +0 -0
  136. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/file_processor_service.py +0 -0
  137. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/history_manager_service.py +0 -0
  138. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/http_tool_service.py +0 -0
  139. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/i18n_service.py +0 -0
  140. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/inference_service.py +0 -0
  141. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/jwt_service.py +0 -0
  142. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/language_service.py +0 -0
  143. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/license_service.py +0 -0
  144. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/llm_client_service.py +0 -0
  145. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/mail_service.py +0 -0
  146. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  147. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/mcp_token_service.py +0 -0
  148. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  149. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  150. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/memory_question_service.py +0 -0
  151. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/memory_service.py +0 -0
  152. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/memory_sources.py +0 -0
  153. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/memory_usage_service.py +0 -0
  154. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  155. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  156. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/operator_identity_service.py +0 -0
  157. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/__init__.py +0 -0
  158. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/contracts.py +0 -0
  159. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  160. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  161. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  162. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  163. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  164. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  165. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  166. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  167. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/parsers/validator.py +0 -0
  168. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/pdf_service.py +0 -0
  169. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/profile_service.py +0 -0
  170. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  171. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/prompt_service.py +0 -0
  172. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  173. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  174. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/sql_service.py +0 -0
  175. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/sql_source_service.py +0 -0
  176. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/storage_service.py +0 -0
  177. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/structured_output_service.py +0 -0
  178. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/system_agent_catalog.py +0 -0
  179. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/system_agent_runner.py +0 -0
  180. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  181. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/system_tools.py +0 -0
  182. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/telemetry_service.py +0 -0
  183. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  184. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/tool_output_contract.py +0 -0
  185. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/tool_service.py +0 -0
  186. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/user_feedback_service.py +0 -0
  187. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/visual_kb_service.py +0 -0
  188. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/visual_tool_service.py +0 -0
  189. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/warmup_service.py +0 -0
  190. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/web_search/__init__.py +0 -0
  191. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  192. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  193. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  194. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/web_search_service.py +0 -0
  195. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
  196. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/images/favicon.ico +0 -0
  197. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/images/favicon.png +0 -0
  198. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  199. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  200. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  201. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  202. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  203. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
  204. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  205. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  206. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  207. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_main.js +0 -0
  208. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  209. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  210. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  211. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  212. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  213. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/account.css +0 -0
  214. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  215. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  216. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/chat_public.css +0 -0
  217. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/documents.css +0 -0
  218. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/landing_page.css +0 -0
  219. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/llm_output.css +0 -0
  220. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/onboarding.css +0 -0
  221. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/static/styles/wiki_page.css +0 -0
  222. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/_chat_header.html +0 -0
  223. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/_company_header.html +0 -0
  224. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/_login_widget.html +0 -0
  225. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/account.html +0 -0
  226. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/base.html +0 -0
  227. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/change_password.html +0 -0
  228. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/chat.html +0 -0
  229. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  230. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/chat_modals.html +0 -0
  231. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/error.html +0 -0
  232. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/forgot_password.html +0 -0
  233. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  234. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/login_global.html +0 -0
  235. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  236. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  237. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/pdf/base.html +0 -0
  238. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/pdf/letter.html +0 -0
  239. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/pdf/report.html +0 -0
  240. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/pdf/simple.html +0 -0
  241. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/signup.html +0 -0
  242. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/templates/wiki_page.html +0 -0
  243. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/__init__.py +0 -0
  244. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/account_view.py +0 -0
  245. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/api_key_api_view.py +0 -0
  246. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/base_login_view.py +0 -0
  247. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/categories_api_view.py +0 -0
  248. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/change_password_view.py +0 -0
  249. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  250. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/chat_view.py +0 -0
  251. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/configuration_api_view.py +0 -0
  252. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/connectors_api_view.py +0 -0
  253. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/embedding_api_view.py +0 -0
  254. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/forgot_password_view.py +0 -0
  255. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/help_content_api_view.py +0 -0
  256. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/history_api_view.py +0 -0
  257. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/home_view.py +0 -0
  258. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/init_context_api_view.py +0 -0
  259. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  260. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/load_document_api_view.py +0 -0
  261. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/login_view.py +0 -0
  262. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/logout_api_view.py +0 -0
  263. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/memory_api_view.py +0 -0
  264. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/profile_api_view.py +0 -0
  265. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/prompt_api_view.py +0 -0
  266. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  267. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  268. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/root_redirect_view.py +0 -0
  269. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/signup_view.py +0 -0
  270. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/static_page_view.py +0 -0
  271. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/tool_api_view.py +0 -0
  272. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  273. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/users_api_view.py +0 -0
  274. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/verify_user_view.py +0 -0
  275. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit/views/wiki_page_view.py +0 -0
  276. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  277. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  278. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit.egg-info/requires.txt +0 -0
  279. {iatoolkit-2.72.1 → iatoolkit-2.72.2}/src/iatoolkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.72.1
3
+ Version: 2.72.2
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- __version__ = "2.72.1"
6
+ __version__ = "2.72.2"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -192,6 +192,38 @@ def filter_llm_models(company_short_name: str, user_identifier: str | None, defa
192
192
  return default_model, allowed
193
193
 
194
194
 
195
+ def stamp(company_short_name: str) -> str | None:
196
+ """A value that changes whenever the company's groups, members or grants change.
197
+
198
+ A person's chat context is built once and cached; when this changes, it is rebuilt
199
+ so the tools, SQL schema and collections it describes follow the new access."""
200
+ decider = Access._decider
201
+ hook = getattr(decider, "stamp", None) if decider is not None else None
202
+ if not callable(hook):
203
+ return None
204
+ try:
205
+ return hook(company_short_name)
206
+ except Exception as exc:
207
+ logging.warning("Access stamp of %s not read: %s", company_short_name, exc)
208
+ return None
209
+
210
+
211
+ def sql_table_filter(company_short_name: str, user_identifier: str | None):
212
+ """`fn(database, table) -> bool` for the SQL schema shown to this person, or None.
213
+
214
+ Some SQL sources hold resources of their own (enterprise's knowledge tables): the
215
+ decider names their resource type, and each table needs level 1 over it."""
216
+ decider = Access._decider
217
+ hook = getattr(decider, "sql_table_resource", None) if decider is not None else None
218
+ if not user_identifier or not callable(hook):
219
+ return None
220
+
221
+ def allowed(database: str, table: str) -> bool:
222
+ resource_type = hook(company_short_name, database)
223
+ return not resource_type or can(company_short_name, user_identifier, USE, resource_type, table)
224
+ return allowed
225
+
226
+
195
227
  def person_can(company_short_name: str, auth_result: dict | None, level: int, resource_type: str = "company",
196
228
  resource_key: str | None = None) -> bool:
197
229
  """A signed-in person's access, from an AuthService result.
@@ -53,6 +53,7 @@ class CompanyContextService:
53
53
  include_yaml_context: bool = True,
54
54
  selected_context_files: List[str] | None = None,
55
55
  allowed_databases: List[str] | None = None,
56
+ table_filter=None,
56
57
  ) -> dict[str, str]:
57
58
  """
58
59
  Builds the full context by aggregating three sources:
@@ -81,7 +82,8 @@ class CompanyContextService:
81
82
  try:
82
83
  # allowed_databases: the sources this person may query (BL-010); None is all.
83
84
  sql_context, db_tables = self._get_sql_enriched_context(company_short_name,
84
- allowed_databases=allowed_databases)
85
+ allowed_databases=allowed_databases,
86
+ table_filter=table_filter)
85
87
  sql_context = sql_context.strip()
86
88
  sql_source_table_scopes = self._get_sql_source_table_scopes(company_short_name)
87
89
  except Exception as e:
@@ -138,11 +140,13 @@ class CompanyContextService:
138
140
  )
139
141
  return files
140
142
 
141
- def get_sql_context(self, company_short_name: str, allowed_databases: List[str] | None = None) -> str:
143
+ def get_sql_context(self, company_short_name: str, allowed_databases: List[str] | None = None,
144
+ table_filter=None) -> str:
142
145
  try:
143
146
  sql_context, _ = self._get_sql_enriched_context(
144
147
  company_short_name,
145
148
  allowed_databases=allowed_databases,
149
+ table_filter=table_filter,
146
150
  )
147
151
  return sql_context
148
152
  except Exception as e:
@@ -177,7 +181,8 @@ class CompanyContextService:
177
181
  return False
178
182
  return bool(cls._table_name_candidates(table_name) & allowed_tables)
179
183
 
180
- def _get_sql_enriched_context(self, company_short_name: str, allowed_databases: List[str] | None = None):
184
+ def _get_sql_enriched_context(self, company_short_name: str, allowed_databases: List[str] | None = None,
185
+ table_filter=None):
181
186
  """
182
187
  Generates the SQL context for the LLM using the enriched schema logic.
183
188
  It iterates over configured databases, fetches their enriched structure,
@@ -221,6 +226,15 @@ class CompanyContextService:
221
226
  }
222
227
  if not enriched_structure:
223
228
  continue
229
+ if table_filter is not None:
230
+ # Tables the person may not query (enterprise's knowledge tables, BL-010).
231
+ enriched_structure = {
232
+ table_name: table_data
233
+ for table_name, table_data in enriched_structure.items()
234
+ if table_filter(db_name, table_name)
235
+ }
236
+ if not enriched_structure:
237
+ continue
224
238
 
225
239
  # 2. Build Header for this Database
226
240
  dialect = self.sql_service.get_database_dialect(company_short_name, db_name)
@@ -19,6 +19,7 @@ from iatoolkit.services.prompt_service import PromptService
19
19
  from iatoolkit.services.structured_output_service import StructuredOutputService
20
20
  from iatoolkit.common.util import Utility
21
21
  from iatoolkit.repositories.models import Company, PromptResourceType
22
+ from iatoolkit.common import access
22
23
 
23
24
 
24
25
  class ContextBuilderService:
@@ -227,7 +228,8 @@ class ContextBuilderService:
227
228
  # sources and collections this person may use (BL-010, Fase 2).
228
229
  allowed_databases, allowed_collections = self._access_restrictions(company_short_name, user_identifier)
229
230
  company_context_blocks = self.company_context_service.get_company_context_blocks(
230
- company_short_name, allowed_databases=allowed_databases)
231
+ company_short_name, allowed_databases=allowed_databases,
232
+ table_filter=access.sql_table_filter(company_short_name, user_identifier))
231
233
  collection_context = "" if allowed_collections == [] else self._build_collection_context(
232
234
  company_short_name, collection_names=allowed_collections)
233
235
 
@@ -386,6 +388,7 @@ class ContextBuilderService:
386
388
  sql_context = self.company_context_service.get_sql_context(
387
389
  company_short_name,
388
390
  allowed_databases=sql_sources,
391
+ table_filter=access.sql_table_filter(company_short_name, user_identifier),
389
392
  )
390
393
 
391
394
  collection_context = ""
@@ -399,6 +402,7 @@ class ContextBuilderService:
399
402
  company_context_blocks = self.company_context_service.get_company_context_blocks(
400
403
  company_short_name,
401
404
  allowed_databases=allowed_databases,
405
+ table_filter=access.sql_table_filter(company_short_name, user_identifier),
402
406
  include_sql_context=bool(company_context_policy.get("sql_context")),
403
407
  include_yaml_context=bool(company_context_policy.get("yaml_context")),
404
408
  )
@@ -610,7 +610,11 @@ class KnowledgeBaseService:
610
610
  else:
611
611
  query = query.filter(Document.status == status)
612
612
 
613
- if collection:
613
+ if isinstance(collection, (list, tuple, set)):
614
+ # Several collections: those a person may see (BL-010). An empty list is none.
615
+ names = [str(c).strip().lower() for c in collection if str(c or "").strip()]
616
+ query = query.join(Document.collection_type).filter(func.lower(CollectionType.name).in_(names or [""]))
617
+ elif collection:
614
618
  normalized_collection = str(collection).strip().lower()
615
619
  query = query.join(Document.collection_type).filter(
616
620
  func.lower(CollectionType.name) == normalized_collection
@@ -962,6 +962,18 @@ class QueryService:
962
962
 
963
963
  return paths
964
964
 
965
+ def _access_changed_since_context(self, company_short_name: str, user_identifier: str) -> bool:
966
+ if not access.Access.registered():
967
+ return False
968
+ current = access.stamp(company_short_name)
969
+ if not current:
970
+ return False
971
+ try:
972
+ built_with = self.session_context.get_access_stamp(company_short_name, user_identifier)
973
+ except Exception:
974
+ return False
975
+ return built_with is not None and built_with != current
976
+
965
977
  def _ensure_valid_history(self, company,
966
978
  user_identifier: str,
967
979
  effective_model: str,
@@ -987,6 +999,10 @@ class QueryService:
987
999
  needs_rebuild = self.history_manager.populate_request_params(
988
1000
  handle, user_turn_prompt, ignore_history
989
1001
  )
1002
+ # A context built before an access change describes tools, SQL sources or
1003
+ # collections the person may no longer use (or misses new ones): rebuild it.
1004
+ if not needs_rebuild and self._access_changed_since_context(company.short_name, user_identifier):
1005
+ needs_rebuild = True
990
1006
 
991
1007
  if needs_rebuild:
992
1008
  logging.warning(f"No valid history for {company.short_name}/{user_identifier}. Rebuilding context...")
@@ -1241,6 +1257,9 @@ class QueryService:
1241
1257
  # Determine if we need to persist the prepared context again.
1242
1258
  rebuild_is_needed = (prev_version != current_version)
1243
1259
 
1260
+ # The access the context was built with: when it changes, the context is rebuilt.
1261
+ self.session_context.save_access_stamp(company_short_name, user_identifier, access.stamp(company_short_name))
1262
+
1244
1263
  # Save the prepared context and its version for `set_context_for_llm` to use.
1245
1264
  self.session_context.save_prepared_context(company_short_name,
1246
1265
  user_identifier,
@@ -101,6 +101,48 @@ class ResourceAccessScope:
101
101
  scoped["allowed_wiki_keys"] = [k for k in allowed if not requested or k in requested]
102
102
  return scoped
103
103
 
104
+ # ---------------------------------------------------------------- the RAG API
105
+ def scope_collection(self, company_short_name: str, user_identifier: str | None, collection,
106
+ *, multi: bool):
107
+ """A collection argument narrowed for this person (the RAG REST API, BL-010).
108
+
109
+ Named collections must all be visible; with none named, the visible ones
110
+ (a list when `multi`, the only one otherwise). Raises PERMISSION."""
111
+ if not user_identifier or not access.Access.registered():
112
+ return collection
113
+ named = _as_list(collection)
114
+ if named:
115
+ denied = [c for c in named if not self._can_see_collection(company_short_name, user_identifier, c)]
116
+ if denied:
117
+ raise _denied(f"No access to the collection '{denied[0]}'.")
118
+ return collection
119
+ allowed = self.allowed_collections(company_short_name, user_identifier)
120
+ if allowed is None:
121
+ return collection
122
+ if not allowed:
123
+ raise _denied("No access to any document collection.")
124
+ if multi:
125
+ return allowed
126
+ if len(allowed) == 1:
127
+ return allowed[0]
128
+ raise _denied("Name the collection: you can see only some of them.")
129
+
130
+ def document_allowed(self, company_short_name: str, user_identifier: str | None, document_id) -> bool:
131
+ if not user_identifier or not access.Access.registered():
132
+ return True
133
+ collection = self._document_collection(company_short_name, document_id)
134
+ return not collection or self._can_see_collection(company_short_name, user_identifier, collection)
135
+
136
+ def visible_collection_filter(self, company_short_name: str, user_identifier: str | None):
137
+ """`fn(collection_name) -> bool` for lists of documents; None when nothing is restricted."""
138
+ if not user_identifier or not access.Access.registered():
139
+ return None
140
+ allowed = self.allowed_collections(company_short_name, user_identifier)
141
+ if allowed is None:
142
+ return None
143
+ allowed_set = set(allowed)
144
+ return lambda name: name in allowed_set
145
+
104
146
  # ------------------------------------------------------------------- listings
105
147
  def allowed_collections(self, company_short_name: str, user_identifier: str | None) -> list[str] | None:
106
148
  """The collections the person may see, or None when nothing is restricted for them."""
@@ -190,6 +190,18 @@ class UserSessionContextService:
190
190
  normalized.append(key)
191
191
  return normalized
192
192
 
193
+ def save_access_stamp(self, company_short_name: str, user_identifier: str, stamp: str | None):
194
+ """The company's access stamp the person's cached context was built with (BL-010)."""
195
+ session_key = self._get_session_key(company_short_name, user_identifier)
196
+ if session_key and stamp:
197
+ RedisSessionManager.hset(session_key, "access_stamp", stamp)
198
+
199
+ def get_access_stamp(self, company_short_name: str, user_identifier: str) -> Optional[str]:
200
+ session_key = self._get_session_key(company_short_name, user_identifier)
201
+ if not session_key:
202
+ return None
203
+ return RedisSessionManager.hget(session_key, "access_stamp")
204
+
193
205
  def save_context_version(self,
194
206
  company_short_name: str,
195
207
  user_identifier: str,
@@ -39,6 +39,35 @@ class RagApiView(MethodView):
39
39
  self.utility = utility
40
40
  self.i18n_service = i18n_service
41
41
 
42
+ # What a person may reach (BL-010): only the collections and documents they may see.
43
+ @staticmethod
44
+ def _access_scope():
45
+ from iatoolkit import current_iatoolkit
46
+ from iatoolkit.services.resource_access_scope import ResourceAccessScope
47
+ return current_iatoolkit().get_injector().get(ResourceAccessScope)
48
+
49
+ def _scoped_collection(self, company_short_name: str, auth_result: dict, collection, *, multi: bool):
50
+ """The collection argument narrowed to what the person sees; raises PERMISSION."""
51
+ from iatoolkit.common import access
52
+ if not access.Access.registered():
53
+ return collection
54
+ return self._access_scope().scope_collection(company_short_name, auth_result.get("user_identifier"),
55
+ collection, multi=multi)
56
+
57
+ def _document_denied(self, company_short_name: str, auth_result: dict, document_id):
58
+ from iatoolkit.common import access
59
+ if not access.Access.registered():
60
+ return None
61
+ if self._access_scope().document_allowed(company_short_name, auth_result.get("user_identifier"), document_id):
62
+ return None
63
+ return jsonify({'result': 'error', 'message': 'No access to that document.'}), 403
64
+
65
+ @staticmethod
66
+ def _permission_denied(exc: IAToolkitException):
67
+ if exc.error_type == IAToolkitException.ErrorType.PERMISSION:
68
+ return jsonify({'result': 'error', 'message': exc.message, 'error_message': exc.message}), 403
69
+ return None
70
+
42
71
  def dispatch_request(self, *args, **kwargs):
43
72
  """
44
73
  Sobreescribimos el dispatch para soportar el mapeo de acciones personalizadas
@@ -111,7 +140,8 @@ class RagApiView(MethodView):
111
140
  keyword = data.get('filename_keyword')
112
141
  from_date_str = data.get('from_date')
113
142
  to_date_str = data.get('to_date')
114
- collection = data.get('collection', '')
143
+ collection = self._scoped_collection(company_short_name, auth_result, data.get('collection', ''),
144
+ multi=True)
115
145
  metadata_key = str(data.get('metadata_key') or '').strip()
116
146
  metadata_value = str(data.get('metadata_value') or '').strip()
117
147
  metadata_match_mode = str(data.get('metadata_match_mode') or '').strip().lower()
@@ -181,6 +211,8 @@ class RagApiView(MethodView):
181
211
  }), 200
182
212
 
183
213
  except IAToolkitException as e:
214
+ if self._permission_denied(e):
215
+ return self._permission_denied(e)
184
216
  return jsonify({'result': 'error', 'message': e.message}), e.http_code
185
217
  except Exception as e:
186
218
  return jsonify({'result': 'error', 'message': str(e)}), 500
@@ -242,6 +274,9 @@ class RagApiView(MethodView):
242
274
  return jsonify(auth_result), auth_result.get("status_code")
243
275
 
244
276
  # 2. Get content from service
277
+ denied = self._document_denied(company_short_name, auth_result, document_id)
278
+ if denied:
279
+ return denied
245
280
  file_bytes, filename = self.knowledge_base_service.get_document_content(document_id)
246
281
 
247
282
  if not file_bytes:
@@ -262,6 +297,8 @@ class RagApiView(MethodView):
262
297
  )
263
298
 
264
299
  except IAToolkitException as e:
300
+ if self._permission_denied(e):
301
+ return self._permission_denied(e)
265
302
  return jsonify({'result': 'error', 'message': e.message}), e.http_code
266
303
  except Exception as e:
267
304
  return jsonify({'result': 'error', 'message': str(e)}), 500
@@ -278,6 +315,9 @@ class RagApiView(MethodView):
278
315
  return jsonify(auth_result), auth_result.get("status_code")
279
316
 
280
317
  # 2. Call Service
318
+ denied = self._document_denied(company_short_name, auth_result, document_id)
319
+ if denied:
320
+ return denied
281
321
  success = self.knowledge_base_service.delete_document(document_id)
282
322
 
283
323
  if success:
@@ -288,6 +328,8 @@ class RagApiView(MethodView):
288
328
  return jsonify({'result': 'error', 'message': msg}), 404
289
329
 
290
330
  except IAToolkitException as e:
331
+ if self._permission_denied(e):
332
+ return self._permission_denied(e)
291
333
  return jsonify({'result': 'error', 'message': e.message}), e.http_code
292
334
  except Exception as e:
293
335
  return jsonify({'result': 'error', 'message': str(e)}), 500
@@ -308,7 +350,7 @@ class RagApiView(MethodView):
308
350
  data = request.get_json() or {}
309
351
  query = data.get('query')
310
352
  n_results = int(data.get('k', 5))
311
- collection = data.get('collection')
353
+ collection = self._scoped_collection(company_short_name, auth_result, data.get('collection'), multi=True)
312
354
  metadata_filter = data.get('metadata_filter')
313
355
  # The Search Lab can compare modes; empty means the company's own.
314
356
  search_mode = str(data.get('search_mode') or '').strip().lower() or None
@@ -340,6 +382,8 @@ class RagApiView(MethodView):
340
382
  }), 200
341
383
 
342
384
  except IAToolkitException as e:
385
+ if self._permission_denied(e):
386
+ return self._permission_denied(e)
343
387
  return jsonify({'result': 'error', 'error_message': e.message}), 501
344
388
  except Exception as e:
345
389
  return jsonify({'result': 'error', 'error_message': str(e)}), 500
@@ -360,6 +404,7 @@ class RagApiView(MethodView):
360
404
  return self._bad_request("query is required", error_code="INVALID_REQUEST")
361
405
 
362
406
  collection, n_results, metadata_filter = self._parse_common_search_params(data)
407
+ collection = self._scoped_collection(company_short_name, auth_result, collection, multi=True)
363
408
 
364
409
  chunks = self.knowledge_base_service.search(
365
410
  company_short_name=company_short_name,
@@ -381,6 +426,8 @@ class RagApiView(MethodView):
381
426
  except ValueError as e:
382
427
  return self._bad_request(str(e), error_code="INVALID_REQUEST")
383
428
  except IAToolkitException as e:
429
+ if self._permission_denied(e):
430
+ return self._permission_denied(e)
384
431
  return jsonify({"result": "error", "error_code": "INTERNAL_ERROR", "message": e.message}), e.http_code
385
432
  except Exception as e:
386
433
  return jsonify({"result": "error", "error_code": "INTERNAL_ERROR", "message": str(e)}), 500
@@ -401,6 +448,7 @@ class RagApiView(MethodView):
401
448
  return self._bad_request("query is required", error_code="INVALID_REQUEST")
402
449
 
403
450
  collection, n_results, metadata_filter = self._parse_common_search_params(data)
451
+ collection = self._scoped_collection(company_short_name, auth_result, collection, multi=False)
404
452
 
405
453
  results = self.visual_kb_service.search_images(
406
454
  company_short_name=company_short_name,
@@ -422,6 +470,8 @@ class RagApiView(MethodView):
422
470
  except ValueError as e:
423
471
  return self._bad_request(str(e), error_code="INVALID_REQUEST")
424
472
  except IAToolkitException as e:
473
+ if self._permission_denied(e):
474
+ return self._permission_denied(e)
425
475
  return jsonify({"result": "error", "error_code": "INTERNAL_ERROR", "message": e.message}), e.http_code
426
476
  except Exception as e:
427
477
  return jsonify({"result": "error", "error_code": "INTERNAL_ERROR", "message": str(e)}), 500
@@ -442,6 +492,7 @@ class RagApiView(MethodView):
442
492
  return self._bad_request("image_base64 is required", error_code="INVALID_REQUEST")
443
493
 
444
494
  collection, n_results, metadata_filter = self._parse_common_search_params(data)
495
+ collection = self._scoped_collection(company_short_name, auth_result, collection, multi=False)
445
496
  image_bytes = self.utility.normalize_base64_payload(image_base64)
446
497
  if not image_bytes:
447
498
  return self._bad_request("image_base64 is empty or invalid", error_code="INVALID_REQUEST")
@@ -466,6 +517,8 @@ class RagApiView(MethodView):
466
517
  except ValueError as e:
467
518
  return self._bad_request(str(e), error_code="INVALID_REQUEST")
468
519
  except IAToolkitException as e:
520
+ if self._permission_denied(e):
521
+ return self._permission_denied(e)
469
522
  return jsonify({"result": "error", "error_code": "INTERNAL_ERROR", "message": e.message}), e.http_code
470
523
  except Exception as e:
471
524
  return jsonify({"result": "error", "error_code": "INTERNAL_ERROR", "message": str(e)}), 500
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.72.1
3
+ Version: 2.72.2
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes