iatoolkit 2.71.1__tar.gz → 2.72.0__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.71.1/src/iatoolkit.egg-info → iatoolkit-2.72.0}/PKG-INFO +1 -1
  2. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/access.py +16 -0
  4. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/locales/en.yaml +57 -1
  5. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/locales/es.yaml +57 -1
  6. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/company_context_service.py +4 -1
  7. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/context_builder_service.py +33 -4
  8. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/dispatcher_service.py +20 -0
  9. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/query_service.py +9 -4
  10. iatoolkit-2.72.0/src/iatoolkit/services/resource_access_scope.py +161 -0
  11. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/tool_service.py +7 -1
  12. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/base_login_view.py +3 -0
  13. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/chat_view.py +3 -0
  14. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/login_view.py +3 -0
  15. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/wiki_page_view.py +6 -1
  16. {iatoolkit-2.71.1 → iatoolkit-2.72.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  17. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit.egg-info/SOURCES.txt +1 -0
  18. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/LICENSE +0 -0
  19. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/LICENSE_COMMUNITY.md +0 -0
  20. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/pyproject.toml +0 -0
  21. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/readme.md +0 -0
  22. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/setup.cfg +0 -0
  23. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/base_company.py +0 -0
  24. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/cli_commands.py +0 -0
  25. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/__init__.py +0 -0
  26. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/bridge_validation.py +0 -0
  27. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/company_paths.py +0 -0
  28. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/exceptions.py +0 -0
  29. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  30. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  31. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  32. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  33. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  34. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  35. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  36. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/memory_tools.py +0 -0
  37. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/model_registry.py +0 -0
  38. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/routes.py +0 -0
  39. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/search_terms.py +0 -0
  40. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/secret_resolver.py +0 -0
  41. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/session_manager.py +0 -0
  42. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/text_splitter.py +0 -0
  43. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/url_safety.py +0 -0
  44. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/common/util.py +0 -0
  45. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/company_registry.py +0 -0
  46. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/__init__.py +0 -0
  47. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  48. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
  49. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
  50. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
  51. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
  52. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
  53. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
  54. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
  55. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  56. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  57. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  58. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  59. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  60. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  61. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  62. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  63. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  64. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  65. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  66. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  67. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  68. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  69. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  70. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  71. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  72. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  73. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  74. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  75. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  76. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  77. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  78. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  79. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  80. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  81. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  82. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  83. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/core.py +0 -0
  84. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/__init__.py +0 -0
  85. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  86. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/call_service.py +0 -0
  87. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  88. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  89. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  90. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  91. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  92. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  93. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  94. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
  95. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  96. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  97. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/inference_handler.py +0 -0
  98. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  99. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  100. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  101. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  102. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  103. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  104. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  105. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  106. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  107. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  108. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/llm_response.py +0 -0
  109. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  110. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/__init__.py +0 -0
  111. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/advisory_lock.py +0 -0
  112. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  113. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/bridge_repo.py +0 -0
  114. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/database_manager.py +0 -0
  115. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  116. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  117. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  118. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  119. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  120. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  121. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
  122. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
  123. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
  124. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/models.py +0 -0
  125. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  126. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  127. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  128. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  129. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  130. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/runtime_logging.py +0 -0
  131. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/__init__.py +0 -0
  132. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/api_key_service.py +0 -0
  133. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  134. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/auth_service.py +0 -0
  135. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/branding_service.py +0 -0
  136. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/configuration_service.py +0 -0
  137. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/embedding_service.py +0 -0
  138. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/excel_service.py +0 -0
  139. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  140. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/history_manager_service.py +0 -0
  141. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/http_tool_service.py +0 -0
  142. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/i18n_service.py +0 -0
  143. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/inference_service.py +0 -0
  144. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/jwt_service.py +0 -0
  145. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  146. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/language_service.py +0 -0
  147. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/license_service.py +0 -0
  148. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/llm_client_service.py +0 -0
  149. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/mail_service.py +0 -0
  150. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  151. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/mcp_token_service.py +0 -0
  152. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  153. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  154. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/memory_question_service.py +0 -0
  155. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/memory_service.py +0 -0
  156. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/memory_sources.py +0 -0
  157. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/memory_usage_service.py +0 -0
  158. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  159. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  160. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/operator_identity_service.py +0 -0
  161. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
  162. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
  163. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  164. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  165. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  166. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  167. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  168. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  169. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  170. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  171. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/parsers/validator.py +0 -0
  172. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/pdf_service.py +0 -0
  173. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/profile_service.py +0 -0
  174. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  175. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/prompt_service.py +0 -0
  176. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  177. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  178. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/sql_service.py +0 -0
  179. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/sql_source_service.py +0 -0
  180. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/storage_service.py +0 -0
  181. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/structured_output_service.py +0 -0
  182. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/system_agent_catalog.py +0 -0
  183. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/system_agent_runner.py +0 -0
  184. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  185. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/system_tools.py +0 -0
  186. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/telemetry_service.py +0 -0
  187. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  188. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/tool_output_contract.py +0 -0
  189. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  190. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  191. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
  192. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
  193. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/warmup_service.py +0 -0
  194. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
  195. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  196. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  197. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  198. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/web_search_service.py +0 -0
  199. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
  200. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/images/favicon.ico +0 -0
  201. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/images/favicon.png +0 -0
  202. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  203. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  204. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  205. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  206. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  207. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
  208. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  209. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  210. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  211. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  212. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  213. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  214. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  215. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  216. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  217. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/account.css +0 -0
  218. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  219. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  220. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  221. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/documents.css +0 -0
  222. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  223. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  224. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  225. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/static/styles/wiki_page.css +0 -0
  226. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/_chat_header.html +0 -0
  227. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/_company_header.html +0 -0
  228. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  229. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/account.html +0 -0
  230. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/base.html +0 -0
  231. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/change_password.html +0 -0
  232. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/chat.html +0 -0
  233. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  234. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  235. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/error.html +0 -0
  236. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  237. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  238. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/login_global.html +0 -0
  239. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  240. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  241. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/pdf/base.html +0 -0
  242. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
  243. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/pdf/report.html +0 -0
  244. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
  245. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/signup.html +0 -0
  246. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/templates/wiki_page.html +0 -0
  247. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/__init__.py +0 -0
  248. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/account_view.py +0 -0
  249. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
  250. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/categories_api_view.py +0 -0
  251. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/change_password_view.py +0 -0
  252. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  253. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
  254. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
  255. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
  256. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  257. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
  258. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/history_api_view.py +0 -0
  259. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/home_view.py +0 -0
  260. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  261. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  262. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
  263. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  264. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/memory_api_view.py +0 -0
  265. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  266. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  267. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  268. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  269. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/rag_api_view.py +0 -0
  270. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
  271. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/signup_view.py +0 -0
  272. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/static_page_view.py +0 -0
  273. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/tool_api_view.py +0 -0
  274. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  275. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/users_api_view.py +0 -0
  276. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  277. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  278. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  279. {iatoolkit-2.71.1 → iatoolkit-2.72.0}/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.71.1
3
+ Version: 2.72.0
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.71.1"
6
+ __version__ = "2.72.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -176,6 +176,22 @@ def role_assigned(company_short_name: str, user_identifier: str, role: str) -> N
176
176
  company_short_name, exc)
177
177
 
178
178
 
179
+ def filter_llm_models(company_short_name: str, user_identifier: str | None, default_model: str | None,
180
+ models: list[dict]) -> tuple[str | None, list[dict]]:
181
+ """The chat's model choice limited to the models this person may use (BL-010, Fase 2).
182
+
183
+ When the company's default is not among them, the first one they may use becomes
184
+ their default."""
185
+ if not user_identifier or not Access.registered():
186
+ return default_model, models
187
+ allowed = [m for m in models or [] if can(company_short_name, user_identifier, USE, "model",
188
+ str((m or {}).get("id") or ""))]
189
+ allowed_ids = [str(m.get("id")) for m in allowed]
190
+ if default_model and default_model not in allowed_ids:
191
+ default_model = allowed_ids[0] if allowed_ids else None
192
+ return default_model, allowed
193
+
194
+
179
195
  def person_can(company_short_name: str, auth_result: dict | None, level: int, resource_type: str = "company",
180
196
  resource_key: str | None = None) -> bool:
181
197
  """A signed-in person's access, from an AuthService result.
@@ -695,6 +695,54 @@ ui:
695
695
  access_all_resources: "every resource"
696
696
  access_company: "the company"
697
697
  access_title: "Access"
698
+ access_person_title: "What this person sees"
699
+ access_group_title: "What this group can do"
700
+ access_person_company: "Over the company"
701
+ access_person_none: "No resource has its own access yet: they use what the whole company uses."
702
+ access_group_none: "Not listed in any resource's access."
703
+ access_no_access: "no access"
704
+ access_role_owner: "Owner"
705
+ access_role_admin: "Administers"
706
+ access_role_editor: "Edits"
707
+ access_role_user: "Uses"
708
+ access_simulator: "Simulate access"
709
+ access_simulator_hint: "Pick a person and a resource: it tells you whether they can, and why."
710
+ access_sim_person: "Person"
711
+ access_sim_type: "Resource type"
712
+ access_sim_key: "Resource (name or key)"
713
+ access_sim_run: "Simulate"
714
+ access_sim_allowed: "Can"
715
+ access_sim_denied: "Cannot"
716
+ access_sim_groups: "Their groups"
717
+ access_reason_owner: "Owns the company: can do everything."
718
+ access_reason_company_admin: "Administers the company: administers every resource."
719
+ access_reason_company: "By their level over the company."
720
+ access_reason_own_access_list: "The resource has its own list: it depends on whether one of their groups is in it."
721
+ access_reason_type_default: "The resource uses the company's access for its type."
722
+ access_export: "Export"
723
+ access_import: "Import permissions"
724
+ access_import_hint: "Paste an exported YAML. Check what would change first, then apply it."
725
+ access_import_check: "Check changes"
726
+ access_import_apply: "Apply"
727
+ access_import_groups_created: "New groups"
728
+ access_import_groups_updated: "Changed groups"
729
+ access_import_members_added: "Members added"
730
+ access_import_members_removed: "Members removed"
731
+ access_import_resources_set: "Resources with their access"
732
+ access_import_errors: "Errors"
733
+ access_import_nothing: "Nothing to change."
734
+ access_import_done: "Permissions imported."
735
+ access_type_agent: "Agent"
736
+ access_type_tool: "Tool"
737
+ access_type_model: "Model"
738
+ access_type_sql_source: "SQL source"
739
+ access_type_rag_collection: "Collection"
740
+ access_type_memory_folder: "Memory folder"
741
+ access_type_knowledge_wiki: "Wiki"
742
+ access_type_knowledge_table: "Knowledge table"
743
+ access_type_mcp_tool: "MCP tool"
744
+ access_type_company: "The company"
745
+ access_settings_tab: "Settings"
698
746
  access_group_owners: "Owners"
699
747
  access_group_admins: "Administrators"
700
748
  access_group_editors: "Editors"
@@ -725,6 +773,13 @@ ui:
725
773
  access_mode_own: "Restricted"
726
774
  access_mode_default: "Whole company"
727
775
  access_heading_agent: "Who can use this agent?"
776
+ access_heading_tool: "Who can use this tool?"
777
+ access_heading_sql_source: "Who can query this SQL source?"
778
+ access_heading_knowledge_table: "Who can query this table?"
779
+ access_heading_model: "Who can use this model?"
780
+ access_heading_knowledge_wiki: "Who can see this wiki?"
781
+ access_heading_rag_collection: "Who can see this collection?"
782
+ access_heading_memory_folder: "Who can see this folder?"
728
783
  access_heading: "Who has access?"
729
784
  access_default: "Company access (default)"
730
785
  access_default_hint: "Everyone uses it under the company's general permissions. Add a group to restrict it."
@@ -837,7 +892,7 @@ ui:
837
892
  mode_external_sync: "External"
838
893
  mode_managed_help: "The wiki is edited from this workspace and pages are saved into storage."
839
894
  mode_external_sync_help: "The wiki stays read-only in IAToolkit and updates from the configured storage root."
840
- access_control: "Access control"
895
+ access_control: "Page visibility by labels"
841
896
  access_mode_off: "Off"
842
897
  access_mode_off_help: "Access labels are stored but no page is filtered."
843
898
  access_mode_dry_run: "Dry run"
@@ -2693,6 +2748,7 @@ errors:
2693
2748
  company_not_found: "The company {company_short_name} does not exist."
2694
2749
  access:
2695
2750
  agent_denied: "You do not have access to the agent {prompt_name}."
2751
+ model_denied: "You do not have access to the model {model}."
2696
2752
  timeout: "timeout expired."
2697
2753
  auth:
2698
2754
  invalid_password: "The provided password is incorrect."
@@ -709,6 +709,54 @@ ui:
709
709
  access_all_resources: "todos los recursos"
710
710
  access_company: "la empresa"
711
711
  access_title: "Acceso"
712
+ access_person_title: "Qué ve esta persona"
713
+ access_group_title: "Qué puede este grupo"
714
+ access_person_company: "Sobre la empresa"
715
+ access_person_none: "Ningún recurso tiene acceso propio todavía: usa lo de toda la empresa."
716
+ access_group_none: "No aparece en la lista de acceso de ningún recurso."
717
+ access_no_access: "sin acceso"
718
+ access_role_owner: "Dueño"
719
+ access_role_admin: "Administra"
720
+ access_role_editor: "Edita"
721
+ access_role_user: "Usa"
722
+ access_simulator: "Simular acceso"
723
+ access_simulator_hint: "Elige una persona y un recurso: te dice si puede y por qué."
724
+ access_sim_person: "Persona"
725
+ access_sim_type: "Tipo de recurso"
726
+ access_sim_key: "Recurso (nombre o clave)"
727
+ access_sim_run: "Simular"
728
+ access_sim_allowed: "Puede"
729
+ access_sim_denied: "No puede"
730
+ access_sim_groups: "Sus grupos"
731
+ access_reason_owner: "Es dueño de la empresa: puede todo."
732
+ access_reason_company_admin: "Administra la empresa: administra todos los recursos."
733
+ access_reason_company: "Según su nivel sobre la empresa."
734
+ access_reason_own_access_list: "El recurso tiene lista propia: decide si alguno de sus grupos está en ella."
735
+ access_reason_type_default: "El recurso usa el acceso de la empresa para su tipo."
736
+ access_export: "Exportar"
737
+ access_import: "Importar permisos"
738
+ access_import_hint: "Pega un YAML exportado. Primero revisa qué cambiaría y después aplícalo."
739
+ access_import_check: "Revisar cambios"
740
+ access_import_apply: "Aplicar"
741
+ access_import_groups_created: "Grupos nuevos"
742
+ access_import_groups_updated: "Grupos modificados"
743
+ access_import_members_added: "Miembros que se agregan"
744
+ access_import_members_removed: "Miembros que se quitan"
745
+ access_import_resources_set: "Recursos con su acceso"
746
+ access_import_errors: "Errores"
747
+ access_import_nothing: "No hay nada que cambiar."
748
+ access_import_done: "Permisos importados."
749
+ access_type_agent: "Agente"
750
+ access_type_tool: "Tool"
751
+ access_type_model: "Modelo"
752
+ access_type_sql_source: "Fuente SQL"
753
+ access_type_rag_collection: "Colección"
754
+ access_type_memory_folder: "Carpeta de Memoria"
755
+ access_type_knowledge_wiki: "Wiki"
756
+ access_type_knowledge_table: "Knowledge table"
757
+ access_type_mcp_tool: "Tool MCP"
758
+ access_type_company: "La empresa"
759
+ access_settings_tab: "Configuración"
712
760
  access_group_owners: "Dueños"
713
761
  access_group_admins: "Administradores"
714
762
  access_group_editors: "Editores"
@@ -739,6 +787,13 @@ ui:
739
787
  access_mode_own: "Restringido"
740
788
  access_mode_default: "Toda la empresa"
741
789
  access_heading_agent: "¿Quién puede usar este agente?"
790
+ access_heading_tool: "¿Quién puede usar esta tool?"
791
+ access_heading_sql_source: "¿Quién puede consultar esta fuente SQL?"
792
+ access_heading_knowledge_table: "¿Quién puede consultar esta tabla?"
793
+ access_heading_model: "¿Quién puede usar este modelo?"
794
+ access_heading_knowledge_wiki: "¿Quién puede ver esta wiki?"
795
+ access_heading_rag_collection: "¿Quién puede ver esta colección?"
796
+ access_heading_memory_folder: "¿Quién puede ver esta carpeta?"
742
797
  access_heading: "¿Quién tiene acceso?"
743
798
  access_default: "Acceso de la empresa (por defecto)"
744
799
  access_default_hint: "Lo usan todos según los permisos generales de la empresa. Agrega un grupo para restringirlo."
@@ -851,7 +906,7 @@ ui:
851
906
  mode_external_sync: "Externa"
852
907
  mode_managed_help: "La wiki se edita desde esta interfaz y guarda sus páginas en storage."
853
908
  mode_external_sync_help: "La wiki queda de solo lectura en IAToolkit y se actualiza desde la raíz storage configurada."
854
- access_control: "Control de acceso"
909
+ access_control: "Visibilidad de páginas por etiquetas"
855
910
  access_mode_off: "Desactivado"
856
911
  access_mode_off_help: "Las etiquetas de acceso se guardan pero no se filtra ninguna página."
857
912
  access_mode_dry_run: "Simulación"
@@ -2708,6 +2763,7 @@ errors:
2708
2763
  company_not_found: "La empresa {company_short_name} no existe."
2709
2764
  access:
2710
2765
  agent_denied: "No tienes acceso al agente {prompt_name}."
2766
+ model_denied: "No tienes acceso al modelo {model}."
2711
2767
  timeout: "El tiempo de espera ha expirado."
2712
2768
 
2713
2769
 
@@ -52,6 +52,7 @@ class CompanyContextService:
52
52
  include_sql_context: bool = True,
53
53
  include_yaml_context: bool = True,
54
54
  selected_context_files: List[str] | None = None,
55
+ allowed_databases: List[str] | None = None,
55
56
  ) -> dict[str, str]:
56
57
  """
57
58
  Builds the full context by aggregating three sources:
@@ -78,7 +79,9 @@ class CompanyContextService:
78
79
  # schema expansion and expose SQL through dedicated schema/query tools.
79
80
  if include_sql_context:
80
81
  try:
81
- sql_context, db_tables = self._get_sql_enriched_context(company_short_name)
82
+ # allowed_databases: the sources this person may query (BL-010); None is all.
83
+ sql_context, db_tables = self._get_sql_enriched_context(company_short_name,
84
+ allowed_databases=allowed_databases)
82
85
  sql_context = sql_context.strip()
83
86
  sql_source_table_scopes = self._get_sql_source_table_scopes(company_short_name)
84
87
  except Exception as e:
@@ -199,7 +199,7 @@ class ContextBuilderService:
199
199
 
200
200
  # 1. Get user profile
201
201
  user_profile = self.profile_service.get_profile_by_identifier(company_short_name, user_identifier)
202
- available_tools = self.tool_service.get_tools_for_llm(company)
202
+ available_tools = self.tool_service.get_tools_for_llm(company, user_identifier=user_identifier)
203
203
 
204
204
  # 2. Render the base system prompt (iatoolkit standard)
205
205
  system_prompt_payload = self.prompt_service.get_system_prompt_payload(
@@ -223,9 +223,13 @@ class ContextBuilderService:
223
223
  service_list=available_tools,
224
224
  )
225
225
 
226
- # 3. Get company specific context (DB Schemas, Docs, etc.)
227
- company_context_blocks = self.company_context_service.get_company_context_blocks(company_short_name)
228
- collection_context = self._build_collection_context(company_short_name)
226
+ # 3. Get company specific context (DB Schemas, Docs, etc.), limited to the SQL
227
+ # sources and collections this person may use (BL-010, Fase 2).
228
+ allowed_databases, allowed_collections = self._access_restrictions(company_short_name, user_identifier)
229
+ company_context_blocks = self.company_context_service.get_company_context_blocks(
230
+ company_short_name, allowed_databases=allowed_databases)
231
+ collection_context = "" if allowed_collections == [] else self._build_collection_context(
232
+ company_short_name, collection_names=allowed_collections)
229
233
 
230
234
  final_system_context = self._join_context_sections(
231
235
  rendered_sections.get("identity"),
@@ -274,6 +278,24 @@ class ContextBuilderService:
274
278
 
275
279
  return capabilities
276
280
 
281
+ def _access_restrictions(self, company_short_name: str,
282
+ user_identifier: str | None) -> tuple[list[str] | None, list[str] | None]:
283
+ """(SQL sources, collections) this person may use; None where nothing is restricted."""
284
+ from iatoolkit.common import access
285
+ if not user_identifier or not access.Access.registered():
286
+ return None, None
287
+ from iatoolkit import current_iatoolkit
288
+ from iatoolkit.services.resource_access_scope import ResourceAccessScope
289
+ from iatoolkit.services.sql_source_service import SqlSourceService
290
+ injector = current_iatoolkit().get_injector()
291
+ scope = injector.get(ResourceAccessScope)
292
+ databases = [str(s.get("database") or "") for s in
293
+ injector.get(SqlSourceService).list_sources(company_short_name, include_inactive=False) or []
294
+ if s.get("database")]
295
+ allowed_databases = scope.allowed_databases(company_short_name, user_identifier, databases)
296
+ return (None if len(allowed_databases) == len(databases) else allowed_databases,
297
+ scope.allowed_collections(company_short_name, user_identifier))
298
+
277
299
  def build_agent_system_context(
278
300
  self,
279
301
  company_short_name: str,
@@ -312,6 +334,12 @@ class ContextBuilderService:
312
334
  resource_bindings,
313
335
  PromptResourceType.RAG_COLLECTION.value,
314
336
  )
337
+ # The agent's sources and collections, minus those this person may not use.
338
+ allowed_databases, allowed_collections = self._access_restrictions(company_short_name, user_identifier)
339
+ if allowed_databases is not None:
340
+ sql_sources = [s for s in sql_sources if s in allowed_databases]
341
+ if allowed_collections is not None:
342
+ rag_collections = [c for c in rag_collections if c in allowed_collections]
315
343
 
316
344
  prompt_capabilities = self._resolve_system_prompt_capabilities(enabled_tools)
317
345
  if self.SQL_TOOL_NAME in enabled_tool_names and not sql_sources:
@@ -370,6 +398,7 @@ class ContextBuilderService:
370
398
  company_context_policy = context_policy.get("company_context_blocks") or {}
371
399
  company_context_blocks = self.company_context_service.get_company_context_blocks(
372
400
  company_short_name,
401
+ allowed_databases=allowed_databases,
373
402
  include_sql_context=bool(company_context_policy.get("sql_context")),
374
403
  include_yaml_context=bool(company_context_policy.get("yaml_context")),
375
404
  )
@@ -56,6 +56,23 @@ class Dispatcher:
56
56
  self._company_instances = None
57
57
  self._company_instances_revision = -1
58
58
 
59
+ @staticmethod
60
+ def _scope_tool_call(company_short_name: str, function_name: str, user_identifier: str | None,
61
+ kwargs: dict) -> dict:
62
+ from iatoolkit.common import access
63
+ if not user_identifier or not access.Access.registered():
64
+ # No person (internal runs), or no groups (core alone): nothing is restricted.
65
+ return kwargs
66
+ from iatoolkit import current_iatoolkit
67
+ from iatoolkit.services.resource_access_scope import ResourceAccessScope
68
+ try:
69
+ injector = current_iatoolkit().get_injector()
70
+ except Exception:
71
+ # No running IAToolkit (unit tests of the dispatcher alone): nothing to scope with.
72
+ return kwargs
73
+ scope = injector.get(ResourceAccessScope)
74
+ return scope.scope_tool_call(company_short_name, function_name, user_identifier, kwargs)
75
+
59
76
  def _safe_rollback(self):
60
77
  """
61
78
  Best-effort rollback for the shared scoped session used by repositories.
@@ -228,6 +245,9 @@ class Dispatcher:
228
245
  )
229
246
  return result
230
247
  try:
248
+ # What the person may reach (BL-010, Fase 2): the tool, and the SQL source,
249
+ # collections or wikis the call names or would search.
250
+ kwargs = self._scope_tool_call(company_short_name, function_name, user_identifier, kwargs)
231
251
  result = self._dispatch_resolved_tool(
232
252
  company_short_name=company_short_name,
233
253
  function_name=function_name,
@@ -1269,7 +1269,7 @@ class QueryService:
1269
1269
  if not prompt_output_contract:
1270
1270
  return {'rebuild_needed': True, 'error': f"Prompt '{prompt_name}' not found"}
1271
1271
 
1272
- tools = self.tool_service.get_tools_for_llm(company)
1272
+ tools = self.tool_service.get_tools_for_llm(company, user_identifier=user_identifier)
1273
1273
  is_agent_execution = self._is_agentic_execution(prompt_output_contract)
1274
1274
  tools, _tool_router_metrics = self._apply_prompt_tool_policy(
1275
1275
  company_short_name=company_short_name,
@@ -1528,6 +1528,11 @@ class QueryService:
1528
1528
  prompt_output_contract=prompt_output_contract,
1529
1529
  )
1530
1530
  effective_model = self._resolve_model(company_short_name, model, prompt_output_contract)
1531
+ # Using a model is a level-1 permission over it (BL-010, Fase 2).
1532
+ if effective_model and not access.can(company_short_name, user_identifier, access.USE, "model",
1533
+ effective_model):
1534
+ return {"error": True, "status_code": 403,
1535
+ "error_message": self.i18n_service.t('errors.access.model_denied', model=effective_model)}
1531
1536
  output_schema = self._build_output_text_schema_payload(
1532
1537
  company_short_name,
1533
1538
  effective_model,
@@ -1616,7 +1621,7 @@ class QueryService:
1616
1621
  is_agent_execution = self._is_agentic_execution(prompt_output_contract) and not is_agent_session_execution
1617
1622
 
1618
1623
  # get the tools availables for this company
1619
- tools = self.tool_service.get_tools_for_llm(company)
1624
+ tools = self.tool_service.get_tools_for_llm(company, user_identifier=user_identifier)
1620
1625
  log_stage("load_tools")
1621
1626
  tools, tool_router_metrics = self._apply_prompt_tool_policy(
1622
1627
  company_short_name=company_short_name,
@@ -1920,7 +1925,7 @@ class QueryService:
1920
1925
  )
1921
1926
 
1922
1927
  is_agent_execution = self._is_agentic_execution(prompt_output_contract)
1923
- tools = self.tool_service.get_tools_for_llm(company)
1928
+ tools = self.tool_service.get_tools_for_llm(company, user_identifier=user_identifier)
1924
1929
  tools, tool_router_metrics = self._apply_prompt_tool_policy(
1925
1930
  company_short_name=company_short_name,
1926
1931
  prompt_output_contract=prompt_output_contract,
@@ -2060,7 +2065,7 @@ class QueryService:
2060
2065
  effective_model = self._resolve_model(company_short_name, None, {})
2061
2066
  provider = self._get_provider(company_short_name, effective_model)
2062
2067
  history_type = self._get_history_type(company_short_name, effective_model)
2063
- tools = self.tool_service.get_tools_for_llm(company)
2068
+ tools = self.tool_service.get_tools_for_llm(company, user_identifier=user_identifier)
2064
2069
  runtime_context, _user_profile, selected_system_prompt_keys = self.context_builder.build_system_context(
2065
2070
  company_short_name,
2066
2071
  user_identifier,
@@ -0,0 +1,161 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ """What a tool call may reach, for the person it runs for (BL-010, Fase 2).
7
+
8
+ Every tool call goes through the dispatcher (chat, API, async tasks, MCP
9
+ projected tools). Before the tool runs, this scopes the call to the resources
10
+ the person may use:
11
+
12
+ - the tool itself (level 1 over "tool", by its name);
13
+ - the SQL source a query names (`database_key`);
14
+ - the RAG collections a document search names; with none named, the search is
15
+ narrowed to the collections the person may see (it no longer reaches all);
16
+ - the document a read asks for, by its collection;
17
+ - the wikis a wiki tool names; a search over every wiki is narrowed likewise.
18
+
19
+ A resource the person may not use raises PERMISSION. A call with no person
20
+ (pipelines, packs: internal runs) is not scoped. Without groups (core alone, or
21
+ nothing restricted) every check passes and the call is unchanged.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from injector import inject
27
+ from sqlalchemy import select
28
+
29
+ from iatoolkit.common import access
30
+ from iatoolkit.common.access import USE
31
+ from iatoolkit.common.exceptions import IAToolkitException
32
+ from iatoolkit.repositories.database_manager import DatabaseManager
33
+ from iatoolkit.repositories.models import CollectionType, Company, Document, KnowledgeWiki
34
+
35
+ SQL_TOOLS = frozenset({"iat_sql_query"})
36
+ COLLECTION_TOOLS = frozenset({"iat_document_search", "iat_document_list", "iat_image_search", "iat_visual_search"})
37
+ DOCUMENT_READ_TOOLS = frozenset({"iat_document_read"})
38
+ WIKI_TOOLS = frozenset({"iat_wiki_search", "iat_wiki_get_page"})
39
+ # Collection tools that accept a list of collections; the others take one.
40
+ MULTI_COLLECTION_TOOLS = frozenset({"iat_document_search"})
41
+
42
+
43
+ class ResourceAccessScope:
44
+ @inject
45
+ def __init__(self, db_manager: DatabaseManager):
46
+ self.db_manager = db_manager
47
+
48
+ @property
49
+ def session(self):
50
+ return self.db_manager.get_session()
51
+
52
+ # ---------------------------------------------------------------- tool calls
53
+ def scope_tool_call(self, company_short_name: str, function_name: str, user_identifier: str | None,
54
+ arguments: dict) -> dict:
55
+ """The call's arguments, narrowed to what the person may reach; raises PERMISSION otherwise."""
56
+ if not user_identifier:
57
+ return arguments
58
+ if not access.can(company_short_name, user_identifier, USE, "tool", function_name):
59
+ raise _denied(f"No access to the tool '{function_name}'.")
60
+
61
+ scoped = dict(arguments)
62
+ if function_name in SQL_TOOLS:
63
+ database = str(scoped.get("database_key") or "").strip()
64
+ if database and not access.can(company_short_name, user_identifier, USE, "sql_source", database):
65
+ raise _denied(f"No access to the SQL source '{database}'.")
66
+
67
+ elif function_name in COLLECTION_TOOLS:
68
+ named = _as_list(scoped.get("collection"))
69
+ if named:
70
+ denied = [c for c in named if not self._can_see_collection(company_short_name, user_identifier, c)]
71
+ if denied:
72
+ raise _denied(f"No access to the collection '{denied[0]}'.")
73
+ else:
74
+ allowed = self.allowed_collections(company_short_name, user_identifier)
75
+ if allowed is not None:
76
+ # Everything the person may see, never the whole corpus.
77
+ if not allowed:
78
+ raise _denied("No access to any document collection.")
79
+ if function_name in MULTI_COLLECTION_TOOLS:
80
+ scoped["collection"] = allowed
81
+ elif len(allowed) == 1:
82
+ scoped["collection"] = allowed[0]
83
+ else:
84
+ # These tools take one collection: someone who sees only some names one.
85
+ raise _denied("Name the collection: you can see only some of them.")
86
+
87
+ elif function_name in DOCUMENT_READ_TOOLS:
88
+ collection = self._document_collection(company_short_name, scoped.get("document_id"))
89
+ if collection and not self._can_see_collection(company_short_name, user_identifier, collection):
90
+ raise _denied("No access to that document.")
91
+
92
+ elif function_name in WIKI_TOOLS:
93
+ wiki_key = str(scoped.get("wiki_key") or "").strip()
94
+ if wiki_key:
95
+ if not access.can(company_short_name, user_identifier, USE, "knowledge_wiki", wiki_key):
96
+ raise _denied(f"No access to the wiki '{wiki_key}'.")
97
+ else:
98
+ allowed = self.allowed_wiki_keys(company_short_name, user_identifier)
99
+ if allowed is not None:
100
+ requested = _as_list(scoped.get("allowed_wiki_keys"))
101
+ scoped["allowed_wiki_keys"] = [k for k in allowed if not requested or k in requested]
102
+ return scoped
103
+
104
+ # ------------------------------------------------------------------- listings
105
+ def allowed_collections(self, company_short_name: str, user_identifier: str | None) -> list[str] | None:
106
+ """The collections the person may see, or None when nothing is restricted for them."""
107
+ names = self._collection_names(company_short_name)
108
+ allowed = [n for n in names if self._can_see_collection(company_short_name, user_identifier, n)]
109
+ return None if len(allowed) == len(names) else allowed
110
+
111
+ def allowed_wiki_keys(self, company_short_name: str, user_identifier: str | None) -> list[str] | None:
112
+ keys = self._wiki_keys(company_short_name)
113
+ allowed = [k for k in keys if access.can(company_short_name, user_identifier, USE, "knowledge_wiki", k)]
114
+ return None if len(allowed) == len(keys) else allowed
115
+
116
+ def allowed_databases(self, company_short_name: str, user_identifier: str | None,
117
+ databases: list[str]) -> list[str]:
118
+ return [d for d in databases if access.can(company_short_name, user_identifier, USE, "sql_source", d)]
119
+
120
+ def _can_see_collection(self, company_short_name: str, user_identifier: str | None, collection: str) -> bool:
121
+ return access.can(company_short_name, user_identifier, USE, "rag_collection", collection)
122
+
123
+ def _company_id(self, company_short_name: str) -> int | None:
124
+ return self.session.execute(select(Company.id).where(Company.short_name == company_short_name)).scalar()
125
+
126
+ def _collection_names(self, company_short_name: str) -> list[str]:
127
+ company_id = self._company_id(company_short_name)
128
+ if company_id is None:
129
+ return []
130
+ return [str(n) for n in self.session.execute(
131
+ select(CollectionType.name).where(CollectionType.company_id == company_id)).scalars()]
132
+
133
+ def _wiki_keys(self, company_short_name: str) -> list[str]:
134
+ company_id = self._company_id(company_short_name)
135
+ if company_id is None:
136
+ return []
137
+ return [str(k) for k in self.session.execute(
138
+ select(KnowledgeWiki.wiki_key).where(KnowledgeWiki.company_id == company_id)).scalars()]
139
+
140
+ def _document_collection(self, company_short_name: str, document_id) -> str | None:
141
+ try:
142
+ doc_id = int(document_id)
143
+ except (TypeError, ValueError):
144
+ return None
145
+ return self.session.execute(
146
+ select(CollectionType.name)
147
+ .join(Document, Document.collection_type_id == CollectionType.id)
148
+ .join(Company, Company.id == Document.company_id)
149
+ .where(Document.id == doc_id, Company.short_name == company_short_name)
150
+ ).scalar()
151
+
152
+
153
+ def _as_list(value) -> list[str]:
154
+ if value is None:
155
+ return []
156
+ values = value if isinstance(value, (list, tuple, set)) else [value]
157
+ return [str(v).strip() for v in values if str(v or "").strip()]
158
+
159
+
160
+ def _denied(message: str) -> IAToolkitException:
161
+ return IAToolkitException(IAToolkitException.ErrorType.PERMISSION, message)
@@ -31,6 +31,7 @@ from iatoolkit.services.system_tools import (
31
31
  )
32
32
  from iatoolkit.services.tool_output_contract import clone_output_contract, normalize_output_contract
33
33
  from iatoolkit import current_iatoolkit
34
+ from iatoolkit.common import access
34
35
 
35
36
 
36
37
  class ToolService:
@@ -1510,9 +1511,11 @@ class ToolService:
1510
1511
 
1511
1512
  return set(required) == set(properties.keys())
1512
1513
 
1513
- def get_tools_for_llm(self, company: Company) -> list[dict]:
1514
+ def get_tools_for_llm(self, company: Company, user_identifier: str | None = None) -> list[dict]:
1514
1515
  """
1515
1516
  Returns the list of tools (System + Company) formatted for the LLM (OpenAI Schema).
1517
+ With a person, only the tools they may use (BL-010, Fase 2): the model is not
1518
+ offered what the dispatcher would refuse.
1516
1519
  """
1517
1520
  tools = []
1518
1521
 
@@ -1537,6 +1540,9 @@ class ToolService:
1537
1540
 
1538
1541
  tools.append(ai_tool)
1539
1542
 
1543
+ if user_identifier and access.Access.registered():
1544
+ tools = [tool for tool in tools
1545
+ if access.can(company.short_name, user_identifier, access.USE, "tool", tool["name"])]
1540
1546
  return tools
1541
1547
 
1542
1548
  def get_always_include_tool_names(self, company_short_name: str, tools: list[dict]) -> list[str]:
@@ -18,6 +18,7 @@ from iatoolkit.common.util import Utility
18
18
  from iatoolkit.services.jwt_service import JWTService
19
19
  from iatoolkit.repositories.models import Company
20
20
  import logging
21
+ from iatoolkit.common import access
21
22
 
22
23
 
23
24
  class BaseLoginView(MethodView):
@@ -81,6 +82,8 @@ class BaseLoginView(MethodView):
81
82
  # --- FAST PATH: Render the chat page directly ---
82
83
  # LLM configuration: default model and availables
83
84
  default_llm_model, available_llm_models = self.config_service.get_llm_configuration(company_short_name)
85
+ default_llm_model, available_llm_models = access.filter_llm_models(
86
+ company_short_name, user_identifier, default_llm_model, available_llm_models)
84
87
  llm_request_defaults = self.config_service.get_llm_request_defaults(company_short_name) or {}
85
88
  llm_default_reasoning_effort = str(
86
89
  ((llm_request_defaults.get("reasoning") or {}).get("effort")) or ""
@@ -6,6 +6,7 @@ from iatoolkit.services.branding_service import BrandingService
6
6
  from iatoolkit.services.configuration_service import ConfigurationService
7
7
  from iatoolkit.services.prompt_service import PromptService
8
8
  from iatoolkit.services.i18n_service import I18nService
9
+ from iatoolkit.common import access
9
10
 
10
11
  class ChatView(MethodView):
11
12
  """
@@ -48,6 +49,8 @@ class ChatView(MethodView):
48
49
  branding_data = self.branding_service.get_company_branding(company_short_name)
49
50
  onboarding_cards = self.config_service.get_configuration(company_short_name, 'onboarding_cards')
50
51
  default_llm_model, available_llm_models = self.config_service.get_llm_configuration(company_short_name)
52
+ default_llm_model, available_llm_models = access.filter_llm_models(
53
+ company_short_name, user_identifier, default_llm_model, available_llm_models)
51
54
  llm_request_defaults = self.config_service.get_llm_request_defaults(company_short_name) or {}
52
55
  llm_default_reasoning_effort = str(
53
56
  ((llm_request_defaults.get("reasoning") or {}).get("effort")) or ""
@@ -22,6 +22,7 @@ from iatoolkit.common.util import Utility
22
22
  import logging
23
23
  import secrets
24
24
  from urllib.parse import urljoin, urlparse
25
+ from iatoolkit.common import access
25
26
 
26
27
 
27
28
  def _normalize_safe_next_target(raw_target: str | None) -> str | None:
@@ -487,6 +488,8 @@ class FinalizeContextView(MethodView):
487
488
  branding_data = self.branding_service.get_company_branding(company_short_name)
488
489
 
489
490
  default_llm_model, available_llm_models = self.config_service.get_llm_configuration(company_short_name)
491
+ default_llm_model, available_llm_models = access.filter_llm_models(
492
+ company_short_name, user_identifier, default_llm_model, available_llm_models)
490
493
  llm_request_defaults = self.config_service.get_llm_request_defaults(company_short_name) or {}
491
494
  llm_default_reasoning_effort = str(
492
495
  ((llm_request_defaults.get("reasoning") or {}).get("effort")) or ""
@@ -16,6 +16,7 @@ from iatoolkit.services.i18n_service import I18nService
16
16
  from iatoolkit.services.markdown_wiki_service import MarkdownWikiService
17
17
  from iatoolkit.services.profile_service import ProfileService
18
18
  from iatoolkit.services.tenant_wiki_service import TenantWikiService
19
+ from iatoolkit.common import access
19
20
 
20
21
 
21
22
  class WikiPageView(MethodView):
@@ -62,7 +63,11 @@ class WikiPageView(MethodView):
62
63
  if self.tenant_wiki_service.viewer_may_read_system_wiki(company_short_name, wiki_key, user_identifier):
63
64
  # A system wiki its feature opened to this person (Memoria for company admins).
64
65
  page_kwargs["include_system"] = True
65
- result = self.tenant_wiki_service.get_page(company_short_name, **page_kwargs)
66
+ if access.can(company_short_name, user_identifier, access.USE, "knowledge_wiki", wiki_key):
67
+ result = self.tenant_wiki_service.get_page(company_short_name, **page_kwargs)
68
+ else:
69
+ # A wiki this person may not see (BL-010, Fase 2).
70
+ result = {"status": TenantWikiService.ACCESS_STATUS_FORBIDDEN}
66
71
  wiki = result.get("wiki") or {}
67
72
  context = {
68
73
  "company_short_name": company_short_name,