digitalkin 1.0.0.dev20__tar.gz → 1.0.0.dev21__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 (232) hide show
  1. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/PKG-INFO +1 -1
  2. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/pyproject.toml +1 -1
  3. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/__version__.py +1 -1
  4. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/community/agno/hitl.py +1 -1
  5. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/exceptions.py +4 -0
  6. digitalkin-1.0.0.dev21/src/digitalkin/grpc_servers/interceptors/permission.py +103 -0
  7. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +2 -1
  8. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +4 -1
  9. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/_base_module.py +35 -0
  10. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/setup/grpc_setup.py +4 -1
  11. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/storage/grpc_storage.py +41 -1
  12. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin.egg-info/PKG-INFO +1 -1
  13. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin.egg-info/SOURCES.txt +1 -0
  14. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/LICENSE +0 -0
  15. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/README.md +0 -0
  16. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/__init__.py +0 -0
  17. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/mock/__init__.py +0 -0
  18. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/mock/mock_pb2.py +0 -0
  19. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  20. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/server_async_insecure.py +0 -0
  21. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/server_async_secure.py +0 -0
  22. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/server_sync_insecure.py +0 -0
  23. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/base_server/server_sync_secure.py +0 -0
  24. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/__init__.py +0 -0
  25. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/echo_module.py +0 -0
  26. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/models/__init__.py +0 -0
  27. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/models/input.py +0 -0
  28. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/models/output.py +0 -0
  29. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/models/secret.py +0 -0
  30. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/models/setup.py +0 -0
  31. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/server.py +0 -0
  32. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/triggers/__init__.py +0 -0
  33. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/bench_module/triggers/message_trigger.py +0 -0
  34. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/modules/__init__.py +0 -0
  35. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/modules/archetype_with_tools_module.py +0 -0
  36. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/modules/cpu_intensive_module.py +0 -0
  37. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/modules/dynamic_setup_module.py +0 -0
  38. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/modules/minimal_llm_module.py +0 -0
  39. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/modules/text_transform_module.py +0 -0
  40. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
  41. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
  42. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
  43. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
  44. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
  45. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/monitoring/tests/test_metrics.py +0 -0
  46. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/client.py +0 -0
  47. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/echo_module.py +0 -0
  48. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/models/__init__.py +0 -0
  49. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/models/input.py +0 -0
  50. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/models/output.py +0 -0
  51. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/models/secret.py +0 -0
  52. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/models/setup.py +0 -0
  53. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/server.py +0 -0
  54. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/triggers/__init__.py +0 -0
  55. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/redis_demo/triggers/message_trigger.py +0 -0
  56. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/services/filesystem_module.py +0 -0
  57. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/examples/services/storage_module.py +0 -0
  58. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/setup.cfg +0 -0
  59. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/__init__.py +0 -0
  60. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/community/__init__.py +0 -0
  61. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/community/agno/__init__.py +0 -0
  62. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/community/agno/agno_adapter.py +0 -0
  63. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/community/agno/agui_tools.py +0 -0
  64. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/community/agno/models.py +0 -0
  65. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/__init__.py +0 -0
  66. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/common/__init__.py +0 -0
  67. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/common/factories.py +0 -0
  68. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/exceptions.py +0 -0
  69. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/job_manager/__init__.py +0 -0
  70. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/job_manager/base_job_manager.py +0 -0
  71. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/job_manager/single_job_manager.py +0 -0
  72. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/profiling/__init__.py +0 -0
  73. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/profiling/step_timer.py +0 -0
  74. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/profiling/task_profiler.py +0 -0
  75. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/resilience/__init__.py +0 -0
  76. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/resilience/bulkhead.py +0 -0
  77. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/resilience/task_supervisor.py +0 -0
  78. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/__init__.py +0 -0
  79. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/base_task_manager.py +0 -0
  80. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
  81. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/module_runner.py +0 -0
  82. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/redis/__init__.py +0 -0
  83. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/redis/proto_streams.py +0 -0
  84. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/redis/redis_client.py +0 -0
  85. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/redis/redis_idempotency.py +0 -0
  86. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/redis/redis_signal.py +0 -0
  87. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/redis/redis_state.py +0 -0
  88. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
  89. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/task_executor.py +0 -0
  90. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/core/task_manager/task_session.py +0 -0
  91. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/exceptions.py +0 -0
  92. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/__init__.py +0 -0
  93. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/_base_server.py +0 -0
  94. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/gateway_servicer.py +0 -0
  95. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/interceptors/__init__.py +0 -0
  96. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/interceptors/request_ids.py +0 -0
  97. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/m2m_call_registry.py +0 -0
  98. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/module_server.py +0 -0
  99. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/module_servicer.py +0 -0
  100. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/stream_registry.py +0 -0
  101. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/stream_session.py +0 -0
  102. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
  103. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/utils/circuit_breaker.py +0 -0
  104. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +0 -0
  105. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/grpc_servers/utils/validators.py +0 -0
  106. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/logger.py +0 -0
  107. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/__init__.py +0 -0
  108. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/agui_mixin.py +0 -0
  109. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/base_mixin.py +0 -0
  110. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/cost_mixin.py +0 -0
  111. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/file_history_mixin.py +0 -0
  112. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
  113. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/logger_mixin.py +0 -0
  114. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/mixins/storage_mixin.py +0 -0
  115. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/__init__.py +0 -0
  116. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/core/__init__.py +0 -0
  117. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/core/job_manager_models.py +0 -0
  118. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/core/redis.py +0 -0
  119. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/core/task_monitor.py +0 -0
  120. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/events/__init__.py +0 -0
  121. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/events/agent_events.py +0 -0
  122. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
  123. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/grpc_servers/circuit_breaker.py +0 -0
  124. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/grpc_servers/m2m.py +0 -0
  125. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/grpc_servers/models.py +0 -0
  126. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/grpc_servers/stream_error_codes.py +0 -0
  127. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/grpc_servers/types.py +0 -0
  128. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/__init__.py +0 -0
  129. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/ag_ui.py +0 -0
  130. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/base_types.py +0 -0
  131. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/module.py +0 -0
  132. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/module_context.py +0 -0
  133. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/module_types.py +0 -0
  134. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/request_metadata.py +0 -0
  135. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/select_schema.py +0 -0
  136. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/setup_types.py +0 -0
  137. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/tool_cache.py +0 -0
  138. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/tool_reference.py +0 -0
  139. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/module/utility.py +0 -0
  140. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/services/__init__.py +0 -0
  141. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/services/cost.py +0 -0
  142. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/services/registry.py +0 -0
  143. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/services/services.py +0 -0
  144. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/services/storage.py +0 -0
  145. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/__init__.py +0 -0
  146. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/gateway.py +0 -0
  147. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/grpc_client.py +0 -0
  148. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/log.py +0 -0
  149. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/module.py +0 -0
  150. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/profiling.py +0 -0
  151. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/queue.py +0 -0
  152. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/redis.py +0 -0
  153. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/resilience.py +0 -0
  154. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/server/__init__.py +0 -0
  155. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/server/channel.py +0 -0
  156. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/server/grpc.py +0 -0
  157. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/server/server.py +0 -0
  158. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/server/servicer.py +0 -0
  159. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/task_manager.py +0 -0
  160. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/utils/__init__.py +0 -0
  161. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/settings/utils/channel.py +0 -0
  162. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/utils/__init__.py +0 -0
  163. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/models/utils/dynamic_schema.py +0 -0
  164. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/__init__.py +0 -0
  165. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/archetype_module.py +0 -0
  166. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/tool_module.py +0 -0
  167. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/trigger_handler.py +0 -0
  168. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/triggers/__init__.py +0 -0
  169. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
  170. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
  171. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
  172. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/py.typed +0 -0
  173. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/__init__.py +0 -0
  174. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/base_strategy.py +0 -0
  175. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/communication/__init__.py +0 -0
  176. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/communication/communication_strategy.py +0 -0
  177. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/communication/default_communication.py +0 -0
  178. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/communication/exceptions.py +0 -0
  179. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/communication/grpc_communication.py +0 -0
  180. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/cost/__init__.py +0 -0
  181. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/cost/cost_strategy.py +0 -0
  182. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/cost/default_cost.py +0 -0
  183. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/cost/exceptions.py +0 -0
  184. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/cost/grpc_cost.py +0 -0
  185. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/filesystem/__init__.py +0 -0
  186. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
  187. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/filesystem/exceptions.py +0 -0
  188. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
  189. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
  190. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/identity/__init__.py +0 -0
  191. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/identity/default_identity.py +0 -0
  192. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  193. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/registry/__init__.py +0 -0
  194. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/registry/default_registry.py +0 -0
  195. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/registry/exceptions.py +0 -0
  196. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/registry/grpc_registry.py +0 -0
  197. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/registry/registry_models.py +0 -0
  198. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/registry/registry_strategy.py +0 -0
  199. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/services_config.py +0 -0
  200. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/services_models.py +0 -0
  201. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/setup/__init__.py +0 -0
  202. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/setup/default_setup.py +0 -0
  203. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/setup/exceptions.py +0 -0
  204. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/setup/setup_strategy.py +0 -0
  205. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/storage/__init__.py +0 -0
  206. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/storage/default_storage.py +0 -0
  207. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/storage/exceptions.py +0 -0
  208. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/storage/storage_strategy.py +0 -0
  209. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/task_manager/__init__.py +0 -0
  210. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/task_manager/default_task_manager.py +0 -0
  211. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/task_manager/exceptions.py +0 -0
  212. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/task_manager/redis_task_manager.py +0 -0
  213. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -0
  214. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/user_profile/__init__.py +0 -0
  215. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
  216. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/user_profile/exceptions.py +0 -0
  217. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/user_profile/grpc_user_profile.py +0 -0
  218. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -0
  219. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/__init__.py +0 -0
  220. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/arg_parser.py +0 -0
  221. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/conditional_schema.py +0 -0
  222. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/development_mode_action.py +0 -0
  223. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/dynamic_schema.py +0 -0
  224. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/exceptions.py +0 -0
  225. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/llm_ready_schema.py +0 -0
  226. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/package_discover.py +0 -0
  227. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/proto_utils.py +0 -0
  228. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin/utils/schema_splitter.py +0 -0
  229. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin.egg-info/dependency_links.txt +0 -0
  230. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin.egg-info/requires.txt +0 -0
  231. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/src/digitalkin.egg-info/top_level.txt +0 -0
  232. {digitalkin-1.0.0.dev20 → digitalkin-1.0.0.dev21}/tests/test_exceptions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 1.0.0.dev20
3
+ Version: 1.0.0.dev21
4
4
  Summary: SDK to build kin used in DigitalKin
5
5
  Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
6
6
  License: Attribution-NonCommercial-ShareAlike 4.0 International
@@ -37,7 +37,7 @@
37
37
  "pydantic-settings>=2.14.1",
38
38
  "redis[hiredis]>=7.4.0,<9",
39
39
  ]
40
- version = "1.0.0.dev20"
40
+ version = "1.0.0.dev21"
41
41
 
42
42
  [project.optional-dependencies]
43
43
  performance = [ "uvloop>=0.21" ]
@@ -5,4 +5,4 @@ from importlib.metadata import PackageNotFoundError, version
5
5
  try:
6
6
  __version__ = version("digitalkin")
7
7
  except PackageNotFoundError:
8
- __version__ = "1.0.0.dev20"
8
+ __version__ = "1.0.0.dev21"
@@ -611,7 +611,7 @@ class AgnoHitlRunner:
611
611
  stream: Any,
612
612
  send: Callable[[BaseAgentRunEvent], Coroutine[Any, Any, None]],
613
613
  thread_id: str,
614
- run_output_cls: type,
614
+ run_output_cls: type[RunOutput],
615
615
  ) -> PauseInfo | None:
616
616
  """Drain an Agno stream, forward events, persist on pause.
617
617
 
@@ -19,6 +19,10 @@ class SecurityError(ServerError):
19
19
  """Error related to security configuration."""
20
20
 
21
21
 
22
+ class PermissionDeniedError(ServerError):
23
+ """Remote service rejected the call with gRPC PERMISSION_DENIED."""
24
+
25
+
22
26
  class ServerStateError(ServerError):
23
27
  """Error related to server state (e.g., already started, not started)."""
24
28
 
@@ -0,0 +1,103 @@
1
+ """Client-side permission middleware for gRPC service-data access.
2
+
3
+ A single cross-cutting interceptor: any unary call a backend rejects with
4
+ ``PERMISSION_DENIED`` surfaces as :class:`PermissionDeniedError`, so callers
5
+ never handle permission per service. Attached on every channel, it covers all
6
+ data services and module-to-module calls uniformly.
7
+
8
+ The interceptor *returns* a terminal denied call rather than raising: raising a
9
+ non-``AioRpcError`` from an aio interceptor leaks into the intercepted call's
10
+ ``__del__`` (grpc only swallows ``AioRpcError``/``CancelledError`` there), so we
11
+ mirror grpc's own ``UnaryUnaryCallResponse`` pattern and raise from ``__await__``.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from typing import TYPE_CHECKING, Any
17
+
18
+ import grpc
19
+ import grpc.aio
20
+
21
+ from digitalkin.grpc_servers.exceptions import PermissionDeniedError
22
+ from digitalkin.logger import logger
23
+
24
+ if TYPE_CHECKING:
25
+ from collections.abc import Awaitable, Callable
26
+
27
+
28
+ class _DeniedUnaryUnaryCall(grpc.aio.UnaryUnaryCall):
29
+ """A finished unary call that raises ``PermissionDeniedError`` when awaited."""
30
+
31
+ def __init__(self, method: str, details: str) -> None:
32
+ self._message = f"[{method}] {details or 'permission denied'}"
33
+ self._details = details
34
+
35
+ def cancel(self) -> bool: # noqa: PLR6301
36
+ return False
37
+
38
+ def cancelled(self) -> bool: # noqa: PLR6301
39
+ return False
40
+
41
+ def done(self) -> bool: # noqa: PLR6301
42
+ return True
43
+
44
+ def add_done_callback(self, unused_callback: Any) -> None:
45
+ """No-op: the call is already finished.
46
+
47
+ Args:
48
+ unused_callback: Ignored; present to satisfy the call interface.
49
+ """
50
+
51
+ def time_remaining(self) -> float | None: # noqa: PLR6301
52
+ return None
53
+
54
+ async def initial_metadata(self) -> grpc.aio.Metadata: # noqa: PLR6301
55
+ return grpc.aio.Metadata()
56
+
57
+ async def trailing_metadata(self) -> grpc.aio.Metadata: # noqa: PLR6301
58
+ return grpc.aio.Metadata()
59
+
60
+ async def code(self) -> grpc.StatusCode: # noqa: PLR6301
61
+ return grpc.StatusCode.PERMISSION_DENIED
62
+
63
+ async def details(self) -> str:
64
+ return self._details
65
+
66
+ async def debug_error_string(self) -> None: # noqa: PLR6301
67
+ return None
68
+
69
+ async def wait_for_connection(self) -> None:
70
+ """No-op: the call already resolved to a permission denial."""
71
+
72
+ def __await__(self) -> Any:
73
+ raise PermissionDeniedError(self._message)
74
+ yield # unreachable; marks this method a generator so it is awaitable
75
+
76
+
77
+ class PermissionClientInterceptor(grpc.aio.UnaryUnaryClientInterceptor):
78
+ """Map a ``PERMISSION_DENIED`` unary reply to ``PermissionDeniedError``."""
79
+
80
+ async def intercept_unary_unary( # noqa: PLR6301
81
+ self,
82
+ continuation: Callable[[grpc.aio.ClientCallDetails, Any], Awaitable[Any]],
83
+ client_call_details: grpc.aio.ClientCallDetails,
84
+ request: Any,
85
+ ) -> Any:
86
+ """Return a denied call on PERMISSION_DENIED, else pass the real call through.
87
+
88
+ Args:
89
+ continuation: Downstream call continuation.
90
+ client_call_details: Original call details.
91
+ request: Request message.
92
+
93
+ Returns:
94
+ The downstream call, or a terminal call raising PermissionDeniedError on await.
95
+ """
96
+ call = await continuation(client_call_details, request)
97
+ if await call.code() == grpc.StatusCode.PERMISSION_DENIED:
98
+ method = client_call_details.method
99
+ method_name = method.decode() if isinstance(method, bytes) else method
100
+ details = await call.details()
101
+ logger.warning("permission denied on %s: %s", method_name, details or "")
102
+ return _DeniedUnaryUnaryCall(method_name, details)
103
+ return call
@@ -16,6 +16,7 @@ import grpc.aio
16
16
 
17
17
  from digitalkin.core.resilience.bulkhead import Bulkhead
18
18
  from digitalkin.grpc_servers.exceptions import CircuitOpenError, ServerError
19
+ from digitalkin.grpc_servers.interceptors.permission import PermissionClientInterceptor
19
20
  from digitalkin.grpc_servers.interceptors.request_ids import RequestIdClientInterceptor
20
21
  from digitalkin.grpc_servers.utils.circuit_breaker import CircuitBreaker
21
22
  from digitalkin.logger import logger
@@ -103,7 +104,7 @@ class GrpcClientWrapper:
103
104
 
104
105
  credentials = self._build_channel_credentials(config)
105
106
  grpc_compression = config.compression.to_grpc()
106
- interceptors = [RequestIdClientInterceptor()]
107
+ interceptors = [RequestIdClientInterceptor(), PermissionClientInterceptor()]
107
108
  if credentials is not None:
108
109
  channel = grpc.aio.secure_channel(
109
110
  config.address,
@@ -4,7 +4,7 @@ from collections.abc import AsyncGenerator
4
4
  from contextlib import asynccontextmanager
5
5
  from typing import Any
6
6
 
7
- from digitalkin.grpc_servers.exceptions import ServerError
7
+ from digitalkin.grpc_servers.exceptions import PermissionDeniedError, ServerError
8
8
  from digitalkin.logger import logger
9
9
 
10
10
 
@@ -28,6 +28,7 @@ class GrpcErrorHandlerMixin:
28
28
  Context for the operation.
29
29
 
30
30
  Raises:
31
+ PermissionDeniedError: Re-raised as-is so the authz status is never masked.
31
32
  ServerError: For gRPC-related errors.
32
33
  service_error_class: For service-specific errors if provided.
33
34
  """
@@ -36,6 +37,8 @@ class GrpcErrorHandlerMixin:
36
37
 
37
38
  try:
38
39
  yield
40
+ except PermissionDeniedError:
41
+ raise
39
42
  except service_error_class as e:
40
43
  # Re-raise service-specific errors as-is
41
44
  msg = f"{service_error_class.__name__} in {operation}: {e}"
@@ -7,6 +7,7 @@ from abc import ABC, abstractmethod
7
7
  from collections.abc import Callable, Coroutine
8
8
  from typing import Any, ClassVar, Generic
9
9
 
10
+ from digitalkin.grpc_servers.exceptions import PermissionDeniedError
10
11
  from digitalkin.grpc_servers.utils.utility_schema_extender import UtilitySchemaExtender
11
12
  from digitalkin.logger import logger
12
13
  from digitalkin.models.module.module import ModuleCodeModel, ModuleStatus
@@ -548,6 +549,10 @@ class BaseModule( # Module SDK base class requires many public methods # noqa:
548
549
  self._status = ModuleStatus.CANCELLED
549
550
  logger.info("Module %s cancelled", self.name, extra=self.context.session.current_ids())
550
551
  raise
552
+ except PermissionDeniedError as e:
553
+ self._status = ModuleStatus.FAILED
554
+ logger.warning("Permission denied in module %s: %s", self.name, e, extra=self.context.session.current_ids())
555
+ await self._notify_permission_denied(self.context.callbacks.send_message, e)
551
556
  except Exception as e:
552
557
  self._status = ModuleStatus.FAILED
553
558
  logger.exception("Error inside module %s", self.name, extra=self.context.session.current_ids())
@@ -564,6 +569,28 @@ class BaseModule( # Module SDK base class requires many public methods # noqa:
564
569
  else:
565
570
  self._status = ModuleStatus.STOPPING
566
571
 
572
+ async def _notify_permission_denied(
573
+ self,
574
+ callback: Callable[..., Coroutine[Any, Any, None]],
575
+ e: PermissionDeniedError,
576
+ ) -> None:
577
+ """Send a PermissionDenied notification to the user via the callback.
578
+
579
+ Args:
580
+ callback: The output callback installed on the module context.
581
+ e: The permission-denied error raised by a service call.
582
+ """
583
+ try:
584
+ await callback(
585
+ ModuleCodeModel(
586
+ code="PermissionDenied",
587
+ short_description="Permission denied",
588
+ message=str(e),
589
+ )
590
+ )
591
+ except Exception:
592
+ logger.exception("Failed to send permission-denied callback", extra=self.context.session.current_ids())
593
+
567
594
  async def prepare(
568
595
  self,
569
596
  setup_data: SetupModelT,
@@ -623,6 +650,14 @@ class BaseModule( # Module SDK base class requires many public methods # noqa:
623
650
  try:
624
651
  await self.prepare(setup_data, callback)
625
652
  timer.mark("prepare")
653
+ except PermissionDeniedError as e:
654
+ self._status = ModuleStatus.FAILED
655
+ logger.warning("Permission denied initializing module: %s", e, extra=self.context.session.current_ids())
656
+ await self._notify_permission_denied(callback, e)
657
+ if done_callback is not None:
658
+ await done_callback(None)
659
+ await self.stop()
660
+ return
626
661
  except Exception as e:
627
662
  self._status = ModuleStatus.FAILED
628
663
  short_description = "Error initializing module"
@@ -12,7 +12,7 @@ from agentic_mesh_protocol.setup.v1 import (
12
12
  from google.protobuf.struct_pb2 import Struct
13
13
  from pydantic import ValidationError
14
14
 
15
- from digitalkin.grpc_servers.exceptions import ServerError
15
+ from digitalkin.grpc_servers.exceptions import PermissionDeniedError, ServerError
16
16
  from digitalkin.grpc_servers.utils.grpc_client_wrapper import GrpcClientWrapper
17
17
  from digitalkin.logger import logger
18
18
  from digitalkin.models.grpc_servers.models import ClientConfig
@@ -59,12 +59,15 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
59
59
  Allow error handling in context.
60
60
 
61
61
  Raises:
62
+ PermissionDeniedError: Service rejected the call with PERMISSION_DENIED.
62
63
  ValueError: Pydantic model validation failed - input data is malformed.
63
64
  ServerError: gRPC communication failed - remote service returned error or is unreachable.
64
65
  SetupServiceError: Unexpected error during setup operation - includes connection/timeout issues.
65
66
  """
66
67
  try:
67
68
  yield
69
+ except PermissionDeniedError:
70
+ raise
68
71
  except ValidationError as e:
69
72
  msg = f"Validation failed for {operation}: {e}"
70
73
  logger.error(
@@ -4,7 +4,7 @@ from agentic_mesh_protocol.storage.v1 import data_pb2, storage_service_pb2_grpc
4
4
  from google.protobuf.struct_pb2 import Struct
5
5
  from pydantic import BaseModel
6
6
 
7
- from digitalkin.grpc_servers.exceptions import CircuitOpenError
7
+ from digitalkin.grpc_servers.exceptions import CircuitOpenError, PermissionDeniedError
8
8
  from digitalkin.grpc_servers.utils.grpc_client_wrapper import GrpcClientWrapper
9
9
  from digitalkin.logger import logger
10
10
  from digitalkin.models.grpc_servers.models import ClientConfig
@@ -84,6 +84,7 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
84
84
  StorageRecord: The corresponding record
85
85
 
86
86
  Raises:
87
+ PermissionDeniedError: If the service rejects the call with PERMISSION_DENIED.
87
88
  StorageServiceError: If there is an error while storing the record
88
89
  """
89
90
  logger.debug("debug:_store collection=%s id=%s", record.collection, record.record_id)
@@ -99,6 +100,10 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
99
100
  )
100
101
  resp = await self.exec_grpc_query("StoreRecord", req)
101
102
  return self._build_record_from_proto(resp.stored_data)
103
+ except PermissionDeniedError:
104
+ # TODO(validate): remove after prod validation
105
+ logger.warning("[VALIDATE PD1] storage StoreRecord permission denied")
106
+ raise
102
107
  except Exception as e:
103
108
  if self._is_circuit_open(e):
104
109
  logger.debug("gRPC StoreRecord skipped (circuit open) for %s:%s", record.collection, record.record_id)
@@ -111,6 +116,9 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
111
116
 
112
117
  Returns:
113
118
  StorageData: The record
119
+
120
+ Raises:
121
+ PermissionDeniedError: If the service rejects the call with PERMISSION_DENIED.
114
122
  """
115
123
  logger.debug("debug:_read context=%s collection=%s id=%s", context, collection, record_id)
116
124
  try:
@@ -121,6 +129,10 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
121
129
  )
122
130
  resp = await self.exec_grpc_query("ReadRecord", req)
123
131
  return self._build_record_from_proto(resp.stored_data)
132
+ except PermissionDeniedError:
133
+ # TODO(validate): remove after prod validation
134
+ logger.warning("[VALIDATE PD1] storage ReadRecord permission denied")
135
+ raise
124
136
  except Exception as e:
125
137
  if self._is_circuit_open(e):
126
138
  logger.debug("gRPC ReadRecord skipped (circuit open) for %s:%s", collection, record_id)
@@ -139,6 +151,9 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
139
151
 
140
152
  Returns:
141
153
  StorageRecord: The updated record, or None on failure.
154
+
155
+ Raises:
156
+ PermissionDeniedError: If the service rejects the call with PERMISSION_DENIED.
142
157
  """
143
158
  logger.debug("debug:_update context=%s collection=%s id=%s", context, collection, record_id)
144
159
  try:
@@ -152,6 +167,10 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
152
167
  )
153
168
  resp = await self.exec_grpc_query("UpdateRecord", req)
154
169
  return self._build_record_from_proto(resp.stored_data)
170
+ except PermissionDeniedError:
171
+ # TODO(validate): remove after prod validation
172
+ logger.warning("[VALIDATE PD1] storage UpdateRecord permission denied")
173
+ raise
155
174
  except Exception as e:
156
175
  if self._is_circuit_open(e):
157
176
  logger.debug("gRPC UpdateRecord skipped (circuit open) for %s:%s", collection, record_id)
@@ -164,6 +183,9 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
164
183
 
165
184
  Returns:
166
185
  bool: True if the record was deleted, False otherwise.
186
+
187
+ Raises:
188
+ PermissionDeniedError: If the service rejects the call with PERMISSION_DENIED.
167
189
  """
168
190
  logger.debug("debug:_remove context=%s collection=%s id=%s", context, collection, record_id)
169
191
  try:
@@ -173,6 +195,10 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
173
195
  record_id=record_id,
174
196
  )
175
197
  await self.exec_grpc_query("RemoveRecord", req)
198
+ except PermissionDeniedError:
199
+ # TODO(validate): remove after prod validation
200
+ logger.warning("[VALIDATE PD1] storage RemoveRecord permission denied")
201
+ raise
176
202
  except Exception as e:
177
203
  if self._is_circuit_open(e):
178
204
  logger.debug("gRPC RemoveRecord skipped (circuit open) for %s:%s", collection, record_id)
@@ -186,6 +212,9 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
186
212
 
187
213
  Returns:
188
214
  list[StorageRecord]: The records found, or an empty list on failure.
215
+
216
+ Raises:
217
+ PermissionDeniedError: If the service rejects the call with PERMISSION_DENIED.
189
218
  """
190
219
  logger.debug("debug:_list context=%s collection=%s", context, collection)
191
220
  try:
@@ -195,6 +224,10 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
195
224
  )
196
225
  resp = await self.exec_grpc_query("ListRecords", req)
197
226
  return [self._build_record_from_proto(r) for r in resp.records]
227
+ except PermissionDeniedError:
228
+ # TODO(validate): remove after prod validation
229
+ logger.warning("[VALIDATE PD1] storage ListRecords permission denied")
230
+ raise
198
231
  except Exception as e:
199
232
  if self._is_circuit_open(e):
200
233
  logger.debug("gRPC ListRecords skipped (circuit open) for %s", collection)
@@ -207,6 +240,9 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
207
240
 
208
241
  Returns:
209
242
  bool: True if the collection was removed, False otherwise.
243
+
244
+ Raises:
245
+ PermissionDeniedError: If the service rejects the call with PERMISSION_DENIED.
210
246
  """
211
247
  try:
212
248
  req = data_pb2.RemoveCollectionRequest(
@@ -214,6 +250,10 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
214
250
  collection=collection,
215
251
  )
216
252
  await self.exec_grpc_query("RemoveCollection", req)
253
+ except PermissionDeniedError:
254
+ # TODO(validate): remove after prod validation
255
+ logger.warning("[VALIDATE PD1] storage RemoveCollection permission denied")
256
+ raise
217
257
  except Exception as e:
218
258
  if self._is_circuit_open(e):
219
259
  logger.debug("gRPC RemoveCollection skipped (circuit open) for %s", collection)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 1.0.0.dev20
3
+ Version: 1.0.0.dev21
4
4
  Summary: SDK to build kin used in DigitalKin
5
5
  Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
6
6
  License: Attribution-NonCommercial-ShareAlike 4.0 International
@@ -95,6 +95,7 @@ src/digitalkin/grpc_servers/module_servicer.py
95
95
  src/digitalkin/grpc_servers/stream_registry.py
96
96
  src/digitalkin/grpc_servers/stream_session.py
97
97
  src/digitalkin/grpc_servers/interceptors/__init__.py
98
+ src/digitalkin/grpc_servers/interceptors/permission.py
98
99
  src/digitalkin/grpc_servers/interceptors/request_ids.py
99
100
  src/digitalkin/grpc_servers/utils/__init__.py
100
101
  src/digitalkin/grpc_servers/utils/circuit_breaker.py