legate 0.1.0

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 (317) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +345 -0
  4. data/bin/legate +13 -0
  5. data/examples/00_quickstart.rb +51 -0
  6. data/examples/01_simple_agent.rb +105 -0
  7. data/examples/02_multi_tool_agent.rb +140 -0
  8. data/examples/03_custom_tool.rb +93 -0
  9. data/examples/04_agent_instructions.rb +84 -0
  10. data/examples/05_state_and_sessions.rb +91 -0
  11. data/examples/06_callbacks.rb +186 -0
  12. data/examples/07_async_jobs.rb +112 -0
  13. data/examples/08_loop_agent.rb +197 -0
  14. data/examples/09_sequential_workflow.rb +40 -0
  15. data/examples/10_parallel_workflow.rb +34 -0
  16. data/examples/11_agent_delegation.rb +24 -0
  17. data/examples/12_http_client_tool.rb +156 -0
  18. data/examples/13_authentication.rb +220 -0
  19. data/examples/14_mcp_client.rb +154 -0
  20. data/examples/15_mcp_server.rb +79 -0
  21. data/examples/16_webhooks.rb +91 -0
  22. data/examples/README_sequential_agents.md +164 -0
  23. data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
  24. data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
  25. data/examples/advanced/auth/excon_middleware.rb +317 -0
  26. data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
  27. data/examples/advanced/auth/fiber_auth_example.rb +281 -0
  28. data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
  29. data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
  30. data/examples/advanced/auth/oauth2_auth.rb +419 -0
  31. data/examples/advanced/auth/oidc_auth.rb +514 -0
  32. data/examples/advanced/auth/openweather_api.rb +251 -0
  33. data/examples/advanced/auth/openweather_tool.rb +153 -0
  34. data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
  35. data/examples/advanced/auth/service_account.rb +135 -0
  36. data/examples/advanced/auth/test_with_httpbin.rb +202 -0
  37. data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
  38. data/examples/advanced/callback_monitoring.rb +679 -0
  39. data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
  40. data/examples/advanced/mas/loop_workflow.rb +28 -0
  41. data/examples/advanced/mas/mock_planner.rb +77 -0
  42. data/examples/advanced/mas/proper_delegation_example.rb +276 -0
  43. data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
  44. data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
  45. data/examples/advanced/mcp/mcp_server_async.rb +76 -0
  46. data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
  47. data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
  48. data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
  49. data/examples/advanced/random_calculator.rb +104 -0
  50. data/examples/advanced/sleep_agent.rb +153 -0
  51. data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
  52. data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
  53. data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
  54. data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
  55. data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
  56. data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
  57. data/examples/tools/oauth2_example.rb +136 -0
  58. data/examples/tools/sleepy_tool.rb +42 -0
  59. data/lib/legate/activity_log.rb +71 -0
  60. data/lib/legate/agent.rb +959 -0
  61. data/lib/legate/agent_code_generator.rb +185 -0
  62. data/lib/legate/agent_definition.rb +812 -0
  63. data/lib/legate/agentic/decision.rb +49 -0
  64. data/lib/legate/agentic/loop.rb +134 -0
  65. data/lib/legate/agentic.rb +5 -0
  66. data/lib/legate/agents/loop_agent.rb +248 -0
  67. data/lib/legate/agents/parallel_agent.rb +163 -0
  68. data/lib/legate/agents/sequential_agent.rb +190 -0
  69. data/lib/legate/agents.rb +14 -0
  70. data/lib/legate/auth/config.rb +148 -0
  71. data/lib/legate/auth/coordinator.rb +218 -0
  72. data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
  73. data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
  74. data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
  75. data/lib/legate/auth/credential.rb +157 -0
  76. data/lib/legate/auth/encryption.rb +108 -0
  77. data/lib/legate/auth/error.rb +94 -0
  78. data/lib/legate/auth/exchanged_credential.rb +180 -0
  79. data/lib/legate/auth/excon_middleware.rb +285 -0
  80. data/lib/legate/auth/http_client_utils.rb +364 -0
  81. data/lib/legate/auth/manager.rb +531 -0
  82. data/lib/legate/auth/manager_store.rb +394 -0
  83. data/lib/legate/auth/middleware_factory.rb +290 -0
  84. data/lib/legate/auth/runner.rb +279 -0
  85. data/lib/legate/auth/scheme.rb +125 -0
  86. data/lib/legate/auth/schemes/api_key.rb +212 -0
  87. data/lib/legate/auth/schemes/google_service_account.rb +108 -0
  88. data/lib/legate/auth/schemes/http_bearer.rb +98 -0
  89. data/lib/legate/auth/schemes/oauth2.rb +396 -0
  90. data/lib/legate/auth/schemes/openid_connect.rb +346 -0
  91. data/lib/legate/auth/schemes/service_account.rb +388 -0
  92. data/lib/legate/auth/schemes.rb +40 -0
  93. data/lib/legate/auth/token_manager.rb +362 -0
  94. data/lib/legate/auth/token_store.rb +86 -0
  95. data/lib/legate/auth/tool_context_extension.rb +97 -0
  96. data/lib/legate/auth/tool_integration.rb +188 -0
  97. data/lib/legate/auth/url_guard.rb +81 -0
  98. data/lib/legate/auth.rb +453 -0
  99. data/lib/legate/callbacks/callback_context.rb +71 -0
  100. data/lib/legate/cli/agent_commands.rb +950 -0
  101. data/lib/legate/cli/auth_commands.rb +520 -0
  102. data/lib/legate/cli/base_command.rb +24 -0
  103. data/lib/legate/cli/deployment_commands.rb +934 -0
  104. data/lib/legate/cli/output_helper.rb +108 -0
  105. data/lib/legate/cli/session_commands.rb +138 -0
  106. data/lib/legate/cli/skaffold_commands.rb +223 -0
  107. data/lib/legate/cli/tool_commands.rb +261 -0
  108. data/lib/legate/cli/web_commands.rb +182 -0
  109. data/lib/legate/cli.rb +40 -0
  110. data/lib/legate/configuration/webhooks.rb +113 -0
  111. data/lib/legate/configuration.rb +39 -0
  112. data/lib/legate/definition_store.rb +23 -0
  113. data/lib/legate/errors.rb +118 -0
  114. data/lib/legate/event.rb +161 -0
  115. data/lib/legate/gemini_ai_beta_patch.rb +39 -0
  116. data/lib/legate/generators/agent_generator.rb +412 -0
  117. data/lib/legate/generators/code_validator.rb +48 -0
  118. data/lib/legate/generators/legate/install_generator.rb +35 -0
  119. data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
  120. data/lib/legate/generators/legate/templates/initializer.rb +18 -0
  121. data/lib/legate/generators/runtime_tool_loader.rb +76 -0
  122. data/lib/legate/generators/tool_generator.rb +408 -0
  123. data/lib/legate/generators.rb +11 -0
  124. data/lib/legate/global_definition_registry.rb +506 -0
  125. data/lib/legate/global_tool_manager.rb +135 -0
  126. data/lib/legate/llm/adapter.rb +69 -0
  127. data/lib/legate/llm/gemini.rb +172 -0
  128. data/lib/legate/llm/ollama.rb +80 -0
  129. data/lib/legate/llm.rb +34 -0
  130. data/lib/legate/mcp/client.rb +320 -0
  131. data/lib/legate/mcp/connection/sse.rb +292 -0
  132. data/lib/legate/mcp/connection/stdio.rb +273 -0
  133. data/lib/legate/mcp/connection_manager.rb +103 -0
  134. data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
  135. data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
  136. data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
  137. data/lib/legate/mcp/tool_wrapper.rb +138 -0
  138. data/lib/legate/mcp/util/schema_converter.rb +134 -0
  139. data/lib/legate/mcp.rb +23 -0
  140. data/lib/legate/plan_executor.rb +375 -0
  141. data/lib/legate/planner.rb +839 -0
  142. data/lib/legate/rails/railtie.rb +43 -0
  143. data/lib/legate/rails.rb +9 -0
  144. data/lib/legate/redaction.rb +32 -0
  145. data/lib/legate/session.rb +299 -0
  146. data/lib/legate/session_service/active_record.rb +300 -0
  147. data/lib/legate/session_service/base.rb +68 -0
  148. data/lib/legate/session_service/event_broadcast.rb +74 -0
  149. data/lib/legate/session_service/in_memory.rb +188 -0
  150. data/lib/legate/tool/metadata_dsl.rb +122 -0
  151. data/lib/legate/tool.rb +276 -0
  152. data/lib/legate/tool_code_generator.rb +103 -0
  153. data/lib/legate/tool_context.rb +350 -0
  154. data/lib/legate/tool_loader.rb +39 -0
  155. data/lib/legate/tool_registry.rb +73 -0
  156. data/lib/legate/tool_result.rb +61 -0
  157. data/lib/legate/tools/agent_tool.rb +187 -0
  158. data/lib/legate/tools/base/http_client.rb +319 -0
  159. data/lib/legate/tools/base/safe_url.rb +56 -0
  160. data/lib/legate/tools/base_async_job_tool.rb +91 -0
  161. data/lib/legate/tools/calculator.rb +89 -0
  162. data/lib/legate/tools/cat_facts.rb +81 -0
  163. data/lib/legate/tools/check_job_status_tool.rb +48 -0
  164. data/lib/legate/tools/current_time_tool.rb +64 -0
  165. data/lib/legate/tools/echo.rb +43 -0
  166. data/lib/legate/tools/http_request_tool.rb +105 -0
  167. data/lib/legate/tools/random_number_tool.rb +64 -0
  168. data/lib/legate/tools/read_webpage_tool.rb +92 -0
  169. data/lib/legate/tools/sleepy_tool.rb +74 -0
  170. data/lib/legate/tools/webhook_tool.rb +146 -0
  171. data/lib/legate/version.rb +5 -0
  172. data/lib/legate/web/app.rb +984 -0
  173. data/lib/legate/web/public/css/main.css +4980 -0
  174. data/lib/legate/web/public/images/favicon-256.png +0 -0
  175. data/lib/legate/web/public/images/favicon-32.png +0 -0
  176. data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
  177. data/lib/legate/web/public/images/legate-logo-light.png +0 -0
  178. data/lib/legate/web/public/js/legate.js +616 -0
  179. data/lib/legate/web/public/styles/main.scss +4402 -0
  180. data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
  181. data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
  182. data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
  183. data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
  184. data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
  185. data/lib/legate/web/routes/api_routes.rb +56 -0
  186. data/lib/legate/web/routes/authentication_routes.rb +1541 -0
  187. data/lib/legate/web/routes/core_routes.rb +111 -0
  188. data/lib/legate/web/routes/documentation_routes.rb +220 -0
  189. data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
  190. data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
  191. data/lib/legate/web/sass_compiler.rb +73 -0
  192. data/lib/legate/web/views/_active_session_info.slim +25 -0
  193. data/lib/legate/web/views/_activity_list.slim +55 -0
  194. data/lib/legate/web/views/_agent_card.slim +56 -0
  195. data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
  196. data/lib/legate/web/views/_agent_status_controls.slim +71 -0
  197. data/lib/legate/web/views/_agent_tool_table.slim +74 -0
  198. data/lib/legate/web/views/_chat_message.slim +95 -0
  199. data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
  200. data/lib/legate/web/views/_display_agent_description.slim +11 -0
  201. data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
  202. data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
  203. data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
  204. data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
  205. data/lib/legate/web/views/_display_agent_model.slim +17 -0
  206. data/lib/legate/web/views/_display_agent_name.slim +42 -0
  207. data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
  208. data/lib/legate/web/views/_display_agent_type.slim +65 -0
  209. data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
  210. data/lib/legate/web/views/_edit_agent_description.slim +16 -0
  211. data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
  212. data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
  213. data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
  214. data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
  215. data/lib/legate/web/views/_edit_agent_model.slim +23 -0
  216. data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
  217. data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
  218. data/lib/legate/web/views/_edit_agent_type.slim +67 -0
  219. data/lib/legate/web/views/_session_error.slim +4 -0
  220. data/lib/legate/web/views/_skeleton.slim +69 -0
  221. data/lib/legate/web/views/_tool_card.slim +9 -0
  222. data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
  223. data/lib/legate/web/views/agent.slim +436 -0
  224. data/lib/legate/web/views/agent_auth.slim +562 -0
  225. data/lib/legate/web/views/agents.slim +369 -0
  226. data/lib/legate/web/views/auth.slim +112 -0
  227. data/lib/legate/web/views/auth_credential_detail.slim +327 -0
  228. data/lib/legate/web/views/auth_credentials.slim +261 -0
  229. data/lib/legate/web/views/auth_debug.slim +94 -0
  230. data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
  231. data/lib/legate/web/views/auth_mapping_new.slim +123 -0
  232. data/lib/legate/web/views/auth_mappings.slim +120 -0
  233. data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
  234. data/lib/legate/web/views/auth_schemes.slim +259 -0
  235. data/lib/legate/web/views/auth_test.slim +418 -0
  236. data/lib/legate/web/views/chat.slim +192 -0
  237. data/lib/legate/web/views/docs_index.slim +105 -0
  238. data/lib/legate/web/views/docs_show.slim +105 -0
  239. data/lib/legate/web/views/error_404.slim +5 -0
  240. data/lib/legate/web/views/index.slim +148 -0
  241. data/lib/legate/web/views/layout.slim +144 -0
  242. data/lib/legate/web/views/tool_detail.slim +87 -0
  243. data/lib/legate/web/views/tools.slim +50 -0
  244. data/lib/legate/web/webhook_listener.rb +367 -0
  245. data/lib/legate/web.rb +9 -0
  246. data/lib/legate.rb +220 -0
  247. data/public/docs/advanced/callbacks.md +828 -0
  248. data/public/docs/advanced/mcp_schema_conversion.md +59 -0
  249. data/public/docs/authentication/api_reference/config.md +210 -0
  250. data/public/docs/authentication/api_reference/credential.md +246 -0
  251. data/public/docs/authentication/api_reference/encryption.md +218 -0
  252. data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
  253. data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
  254. data/public/docs/authentication/api_reference/index.md +30 -0
  255. data/public/docs/authentication/api_reference/scheme.md +250 -0
  256. data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
  257. data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
  258. data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
  259. data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
  260. data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
  261. data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
  262. data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
  263. data/public/docs/authentication/api_reference/token_manager.md +221 -0
  264. data/public/docs/authentication/api_reference/token_store.md +146 -0
  265. data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
  266. data/public/docs/authentication/guides/api_key.md +190 -0
  267. data/public/docs/authentication/guides/bearer.md +172 -0
  268. data/public/docs/authentication/guides/configuration.md +255 -0
  269. data/public/docs/authentication/guides/custom_flow.md +523 -0
  270. data/public/docs/authentication/guides/index.md +24 -0
  271. data/public/docs/authentication/guides/migration.md +435 -0
  272. data/public/docs/authentication/guides/oauth2.md +252 -0
  273. data/public/docs/authentication/guides/oidc.md +241 -0
  274. data/public/docs/authentication/guides/overview.md +155 -0
  275. data/public/docs/authentication/guides/secure_storage.md +301 -0
  276. data/public/docs/authentication/guides/service_account.md +228 -0
  277. data/public/docs/authentication/guides/token_lifecycle.md +295 -0
  278. data/public/docs/authentication/guides/web_ui_integration.md +504 -0
  279. data/public/docs/authentication/index.md +58 -0
  280. data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
  281. data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
  282. data/public/docs/authentication/troubleshooting/index.md +11 -0
  283. data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
  284. data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
  285. data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
  286. data/public/docs/cli/legate_cli_usage.md +363 -0
  287. data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
  288. data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
  289. data/public/docs/core_concepts/legate_configuration.md +116 -0
  290. data/public/docs/core_concepts/legate_definition_store.md +102 -0
  291. data/public/docs/core_concepts/legate_planner.md +94 -0
  292. data/public/docs/core_concepts/legate_session_service.md +104 -0
  293. data/public/docs/error_handling/legate_error_handling.md +122 -0
  294. data/public/docs/examples.md +199 -0
  295. data/public/docs/getting_started.md +111 -0
  296. data/public/docs/guides/agentic_agents.md +137 -0
  297. data/public/docs/guides/ai_code_generators.md +437 -0
  298. data/public/docs/guides/auto_loading.md +326 -0
  299. data/public/docs/guides/configuring_agent_webhooks.md +219 -0
  300. data/public/docs/guides/http_client_usage.md +264 -0
  301. data/public/docs/guides/llm_providers.md +137 -0
  302. data/public/docs/guides/mcp_client_integration.md +232 -0
  303. data/public/docs/guides/mcp_server_exposure.md +206 -0
  304. data/public/docs/guides/rails_integration.md +128 -0
  305. data/public/docs/guides/sending_outbound_webhooks.md +227 -0
  306. data/public/docs/guides/streaming.md +112 -0
  307. data/public/docs/guides/webhooks.md +288 -0
  308. data/public/docs/introduction.md +51 -0
  309. data/public/docs/multi_agent_systems/advanced_features.md +57 -0
  310. data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
  311. data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
  312. data/public/docs/multi_agent_systems/state_management.md +47 -0
  313. data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
  314. data/public/docs/tools/legate_built_in_tools.md +332 -0
  315. data/public/docs/tools/legate_tools_and_registry.md +263 -0
  316. data/public/docs/web_ui/legate_web_ui.md +137 -0
  317. metadata +823 -0
@@ -0,0 +1,218 @@
1
+ # Encryption Utilities
2
+
3
+ ## Overview
4
+
5
+ The `Legate::Auth::Encryption` module provides utilities for securely encrypting sensitive authentication data, such as access tokens and refresh tokens. It provides class-level methods for encryption and decryption operations.
6
+
7
+ Encryption is **opt-in**: it is not wired into `TokenStore` automatically (see [Integration with TokenStore](#integration-with-tokenstore) below). The module uses the [rbnacl](https://github.com/RubyCrypto/rbnacl) gem (libsodium SecretBox) for authenticated encryption. `rbnacl` is an **optional/development dependency** — the encryption methods lazily `require 'rbnacl'` and raise `LoadError` if it (or libsodium) is not installed. Add `gem 'rbnacl'` to your Gemfile and ensure libsodium is available to use this module.
8
+
9
+ ## Module Definition
10
+
11
+ ```ruby
12
+ module Legate
13
+ module Auth
14
+ module Encryption
15
+ class << self
16
+ # Encryption class methods
17
+ end
18
+ end
19
+ end
20
+ end
21
+ ```
22
+
23
+ ## Key Features
24
+
25
+ - Secure encryption of sensitive authentication data
26
+ - Authenticated encryption to prevent tampering
27
+ - Base64 encoding for safe storage and transmission
28
+ - Simple class-level interface for encryption and decryption
29
+ - Key generation utility
30
+ - Detection of already-encrypted data
31
+
32
+ ## Class Methods
33
+
34
+ ### `encrypt`
35
+
36
+ Encrypts the provided data.
37
+
38
+ **Parameters:**
39
+ - `data` (String): The data to encrypt (coerced to a string)
40
+ - `key` (String, optional): The Base64-encoded encryption key. When omitted (`nil`), the key is read from the `LEGATE_AUTH_ENCRYPTION_KEY` environment variable.
41
+
42
+ **Returns:**
43
+ - String: The encrypted data, prefixed with the `LGTAUTH` header followed by Base64-encoded ciphertext
44
+
45
+ **Raises:**
46
+ - `LoadError`: If the `rbnacl` gem is not available
47
+ - `ArgumentError`: If no key is supplied and `LEGATE_AUTH_ENCRYPTION_KEY` is unset, or the key is not valid Base64
48
+
49
+ **Examples:**
50
+
51
+ ```ruby
52
+ # Encrypt using the key from LEGATE_AUTH_ENCRYPTION_KEY
53
+ encrypted = Legate::Auth::Encryption.encrypt(sensitive_data)
54
+
55
+ # Encrypt data with a specific (Base64-encoded) key
56
+ encrypted = Legate::Auth::Encryption.encrypt(sensitive_data, my_key)
57
+ ```
58
+
59
+ > There is no built-in default key. If neither an explicit key nor `LEGATE_AUTH_ENCRYPTION_KEY` is provided, an `ArgumentError` is raised.
60
+
61
+ ### `decrypt`
62
+
63
+ Decrypts previously encrypted data.
64
+
65
+ **Parameters:**
66
+ - `encrypted_data` (String): The encrypted data (the `LGTAUTH`-prefixed string returned by `encrypt`)
67
+ - `key` (String, optional): The Base64-encoded encryption key. When omitted (`nil`), the key is read from `LEGATE_AUTH_ENCRYPTION_KEY`.
68
+
69
+ **Returns:**
70
+ - String: The decrypted data
71
+
72
+ **Raises:**
73
+ - `LoadError`: If the `rbnacl` gem is not available
74
+ - `ArgumentError`: If the data is not in the expected format, the key is missing/invalid, or decryption fails
75
+
76
+ **Examples:**
77
+
78
+ ```ruby
79
+ # Decrypt using the key from LEGATE_AUTH_ENCRYPTION_KEY
80
+ decrypted = Legate::Auth::Encryption.decrypt(encrypted_data)
81
+
82
+ # Decrypt data with a specific (Base64-encoded) key
83
+ decrypted = Legate::Auth::Encryption.decrypt(encrypted_data, my_key)
84
+ ```
85
+
86
+ ### `generate_key`
87
+
88
+ Generates a new random encryption key, suitable for use as the `key` argument or `LEGATE_AUTH_ENCRYPTION_KEY`.
89
+
90
+ **Returns:**
91
+ - String: A new random key, Base64-encoded
92
+
93
+ **Raises:**
94
+ - `LoadError`: If the `rbnacl` gem is not available
95
+
96
+ **Examples:**
97
+
98
+ ```ruby
99
+ key = Legate::Auth::Encryption.generate_key
100
+ # => Base64-encoded string, e.g. "k7Qz...=="
101
+ ```
102
+
103
+ ### `encrypted?`
104
+
105
+ Checks if the provided data appears to be encrypted.
106
+
107
+ **Parameters:**
108
+ - `data` (Object): The data to check
109
+
110
+ **Returns:**
111
+ - Boolean: `true` if the data appears to be encrypted
112
+
113
+ **Examples:**
114
+
115
+ ```ruby
116
+ if Legate::Auth::Encryption.encrypted?(data)
117
+ # Data is already encrypted
118
+ else
119
+ # Data needs to be encrypted
120
+ end
121
+ ```
122
+
123
+ ## Usage Examples
124
+
125
+ ### Encrypting Authentication Tokens
126
+
127
+ ```ruby
128
+ # Encrypt authentication tokens
129
+ tokens = {
130
+ access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
131
+ refresh_token: 'rtok_abc123...',
132
+ expires_at: Time.now.to_i + 3600
133
+ }
134
+
135
+ encrypted_tokens = Legate::Auth::Encryption.encrypt(tokens.to_json)
136
+ ```
137
+
138
+ ### Decrypting Authentication Tokens
139
+
140
+ ```ruby
141
+ # Decrypt authentication tokens
142
+ decrypted_json = Legate::Auth::Encryption.decrypt(encrypted_tokens)
143
+ decrypted_tokens = JSON.parse(decrypted_json, symbolize_names: true)
144
+
145
+ access_token = decrypted_tokens[:access_token]
146
+ refresh_token = decrypted_tokens[:refresh_token]
147
+ ```
148
+
149
+ ### Using a Custom Key
150
+
151
+ ```ruby
152
+ # Generate a key
153
+ key = Legate::Auth::Encryption.generate_key
154
+
155
+ # Encrypt with the key
156
+ encrypted = Legate::Auth::Encryption.encrypt(data, key)
157
+
158
+ # Decrypt with the same key
159
+ decrypted = Legate::Auth::Encryption.decrypt(encrypted, key)
160
+ ```
161
+
162
+ ## Integration with TokenStore
163
+
164
+ > **Note:** `Encryption` is **not** wired into `TokenStore`. `TokenStore#store` persists the plaintext result of `token.to_h` into scoped session state, and `TokenStore#get` reads it back as-is. There is no transparent encryption layer.
165
+
166
+ If you need at-rest encryption, apply the `Encryption` module yourself — for example, encrypt the serialized token before persisting it through your own storage layer, and decrypt on read:
167
+
168
+ ```ruby
169
+ # Opt-in: encrypt the serialized token yourself before persisting
170
+ require 'json'
171
+
172
+ key = ENV['LEGATE_AUTH_ENCRYPTION_KEY'] # or Legate::Auth::Encryption.generate_key
173
+ ciphertext = Legate::Auth::Encryption.encrypt(token.to_h.to_json, key)
174
+ # ...persist `ciphertext` wherever you control storage...
175
+
176
+ # On read:
177
+ plaintext = Legate::Auth::Encryption.decrypt(ciphertext, key)
178
+ token = Legate::Auth::ExchangedCredential.from_h(JSON.parse(plaintext, symbolize_names: true))
179
+ ```
180
+
181
+ ## Key Management
182
+
183
+ Best practices for key management include:
184
+
185
+ 1. **Environment Variables**: Store the Base64-encoded key in `LEGATE_AUTH_ENCRYPTION_KEY`
186
+ 2. **Secrets Manager**: Use a secrets manager to securely store and retrieve the key
187
+ 3. **Key Rotation**: Implement a key rotation strategy for enhanced security
188
+ 4. **Consistent Key**: Ensure the same key is used for encryption and decryption
189
+
190
+ ## Security Considerations
191
+
192
+ - **Key Security**: Protect the encryption key and never hard-code it
193
+ - **Secure Key Generation**: Use `generate_key` for cryptographically secure keys
194
+ - **Token TTL**: Implement a time-to-live (TTL) for tokens to limit exposure
195
+ - **Memory Handling**: Clear sensitive data from memory after use when possible
196
+
197
+ ## Error Handling
198
+
199
+ Decryption failures (bad format, wrong key, tampered data) raise `ArgumentError`. A missing `rbnacl` gem raises `LoadError`. There is no dedicated `EncryptionError` class.
200
+
201
+ ```ruby
202
+ begin
203
+ decrypted_data = Legate::Auth::Encryption.decrypt(encrypted_data)
204
+ rescue LoadError => e
205
+ # rbnacl / libsodium not installed
206
+ log.error("Encryption unavailable: #{e.message}")
207
+ nil
208
+ rescue ArgumentError => e
209
+ # Decryption failed: invalid format, key, or tampered data
210
+ log.error("Decryption failed: #{e.message}")
211
+ nil
212
+ end
213
+ ```
214
+
215
+ ## Related Classes
216
+
217
+ - [`Legate::Auth::TokenStore`](./token_store): Secure storage for authentication tokens
218
+ - [`Legate::Auth::TokenManager`](./token_manager): Token lifecycle management
@@ -0,0 +1,271 @@
1
+ # Legate::Auth::ExchangedCredential
2
+
3
+ The `ExchangedCredential` class represents authentication tokens obtained through credential exchange (e.g., OAuth2 access tokens, service account tokens). It provides a consistent interface for handling different types of tokens and their associated metadata.
4
+
5
+ ## Overview
6
+
7
+ After authenticating with an authentication scheme, a credential is exchanged for a token. The `ExchangedCredential` class encapsulates this token along with additional information like token type, expiration time, and refresh tokens.
8
+
9
+ ## Class Methods
10
+
11
+ ### `new`
12
+
13
+ Creates a new exchanged credential (token) instance.
14
+
15
+ **Parameters:**
16
+ - `auth_type` (Symbol, required keyword): The type of authentication (e.g., `:oauth2`, `:service_account`)
17
+ - `access_token` (String, required keyword): The access token
18
+ - `refresh_token` (String, optional keyword): The refresh token (default: nil)
19
+ - `token_type` (String, optional keyword): The type of token (default: 'Bearer')
20
+ - `expires_in` (Integer, optional keyword): Seconds until expiration (default: nil)
21
+ - `id_token` (String, optional keyword): The ID token for OIDC flows (default: nil)
22
+ - `provider_id` (String, optional keyword): The provider identifier (default: nil)
23
+ - `**attributes` (Hash): Additional attributes specific to the token type
24
+
25
+ **Examples:**
26
+
27
+ ```ruby
28
+ # Create an OAuth2 token
29
+ token = Legate::Auth::ExchangedCredential.new(
30
+ auth_type: :oauth2,
31
+ access_token: 'your-access-token',
32
+ refresh_token: 'your-refresh-token',
33
+ expires_in: 3600,
34
+ token_type: 'Bearer'
35
+ )
36
+
37
+ # Create a service account token
38
+ token = Legate::Auth::ExchangedCredential.new(
39
+ auth_type: :service_account,
40
+ access_token: 'your-access-token',
41
+ expires_in: 3600
42
+ )
43
+
44
+ # Create an OIDC token with id_token
45
+ token = Legate::Auth::ExchangedCredential.new(
46
+ auth_type: :oauth2,
47
+ access_token: 'your-access-token',
48
+ refresh_token: 'your-refresh-token',
49
+ id_token: 'jwt-id-token',
50
+ expires_in: 3600
51
+ )
52
+ ```
53
+
54
+ ### `from_h`
55
+
56
+ Creates an ExchangedCredential from a hash representation.
57
+
58
+ **Parameters:**
59
+ - `hash` (Hash): The hash to create the credential from
60
+
61
+ **Returns:**
62
+ - Legate::Auth::ExchangedCredential: A new ExchangedCredential instance
63
+
64
+ **Examples:**
65
+
66
+ ```ruby
67
+ token = Legate::Auth::ExchangedCredential.from_h(saved_token_hash)
68
+ ```
69
+
70
+ ## Instance Methods
71
+
72
+ ### `[]` (accessor)
73
+
74
+ Gets an attribute from the token.
75
+
76
+ **Parameters:**
77
+ - `name` (Symbol, String): The attribute name
78
+
79
+ **Returns:**
80
+ - Object: The attribute value, or nil if not present
81
+
82
+ **Examples:**
83
+
84
+ ```ruby
85
+ token = Legate::Auth::ExchangedCredential.new(
86
+ auth_type: :oauth2,
87
+ access_token: 'your-access-token',
88
+ refresh_token: 'your-refresh-token'
89
+ )
90
+
91
+ access_token = token[:access_token]
92
+ refresh_token = token[:refresh_token]
93
+ ```
94
+
95
+ ### `to_h`
96
+
97
+ Converts the token to a hash.
98
+
99
+ **Returns:**
100
+ - Hash: A hash representation of the token
101
+
102
+ **Examples:**
103
+
104
+ ```ruby
105
+ token = Legate::Auth::ExchangedCredential.new(
106
+ auth_type: :oauth2,
107
+ access_token: 'your-access-token',
108
+ refresh_token: 'your-refresh-token',
109
+ expires_in: 3600
110
+ )
111
+
112
+ token_hash = token.to_h
113
+ # => {auth_type: :oauth2, access_token: "your-access-token", refresh_token: "your-refresh-token", ...}
114
+ ```
115
+
116
+ ### `with`
117
+
118
+ Returns a new ExchangedCredential with updated attributes.
119
+
120
+ **Parameters:**
121
+ - `attrs` (Hash): The attributes to update
122
+
123
+ **Returns:**
124
+ - Legate::Auth::ExchangedCredential: A new instance with the updated attributes
125
+
126
+ **Examples:**
127
+
128
+ ```ruby
129
+ new_token = token.with(access_token: 'new-access-token', expires_in: 7200)
130
+ ```
131
+
132
+ ### `expired?`
133
+
134
+ Checks if the token is expired.
135
+
136
+ **Parameters:**
137
+ - `buffer_seconds` (Integer, optional): Buffer time in seconds before actual expiration (default: 30)
138
+
139
+ **Returns:**
140
+ - Boolean: `true` if the token is expired or will expire within the buffer time
141
+
142
+ **Examples:**
143
+
144
+ ```ruby
145
+ token = Legate::Auth::ExchangedCredential.new(
146
+ auth_type: :oauth2,
147
+ access_token: 'your-access-token',
148
+ expires_in: 3600
149
+ )
150
+
151
+ # Check if expired (with default 30-second buffer)
152
+ puts token.expired?
153
+ # => false
154
+
155
+ # Check if expires within the next 5 minutes
156
+ puts token.expired?(300)
157
+ # => false (if more than 5 minutes remaining)
158
+ ```
159
+
160
+ ### `refreshable?`
161
+
162
+ Checks if the token can be refreshed (i.e., has a refresh token).
163
+
164
+ **Returns:**
165
+ - Boolean: `true` if the token has a refresh token and can be refreshed
166
+
167
+ **Examples:**
168
+
169
+ ```ruby
170
+ token = Legate::Auth::ExchangedCredential.new(
171
+ auth_type: :oauth2,
172
+ access_token: 'your-access-token',
173
+ refresh_token: 'your-refresh-token'
174
+ )
175
+
176
+ puts token.refreshable?
177
+ # => true
178
+
179
+ token_without_refresh = Legate::Auth::ExchangedCredential.new(
180
+ auth_type: :api_key,
181
+ access_token: 'your-api-key'
182
+ )
183
+
184
+ puts token_without_refresh.refreshable?
185
+ # => false
186
+ ```
187
+
188
+ ### `id_token_claims`
189
+
190
+ Decodes and returns the claims from the ID token (for OIDC tokens).
191
+
192
+ **Returns:**
193
+ - Hash: The decoded ID token claims, or nil if no ID token is present
194
+
195
+ **Examples:**
196
+
197
+ ```ruby
198
+ token = Legate::Auth::ExchangedCredential.new(
199
+ auth_type: :oauth2,
200
+ access_token: 'your-access-token',
201
+ id_token: 'jwt-id-token'
202
+ )
203
+
204
+ claims = token.id_token_claims
205
+ puts claims['sub'] # => "user-id"
206
+ puts claims['email'] # => "user@example.com"
207
+ ```
208
+
209
+ ## Common Token Attributes
210
+
211
+ Different token types have different attributes, but some common ones include:
212
+
213
+ | Attribute | Description | Token Types |
214
+ |-----------|-------------|------------|
215
+ | `access_token` | The access token used for authentication | All |
216
+ | `refresh_token` | Token used to refresh the access token | OAuth2, OIDC |
217
+ | `id_token` | JWT token containing user identity | OIDC |
218
+ | `expires_in` | Seconds until the token expires | OAuth2, OIDC, Service Account |
219
+ | `token_type` | Type of token (default: 'Bearer') | OAuth2, OIDC |
220
+ | `provider_id` | The provider identifier | Any |
221
+
222
+ ## Working with Token Expiration
223
+
224
+ Managing token expiration is a common task:
225
+
226
+ ```ruby
227
+ token = Legate::Auth::ExchangedCredential.new(
228
+ auth_type: :oauth2,
229
+ access_token: 'your-access-token',
230
+ expires_in: 3600
231
+ )
232
+
233
+ # Check if expired (30-second buffer by default)
234
+ if token.expired?
235
+ # Token needs to be refreshed
236
+ else
237
+ # Token is still valid
238
+ end
239
+
240
+ # Check if expiring soon (within 5 minutes)
241
+ if token.expired?(300)
242
+ # Token will expire soon, consider refreshing
243
+ end
244
+ ```
245
+
246
+ ## Secure Token Storage
247
+
248
+ ExchangedCredential objects contain sensitive information and should be handled securely:
249
+
250
+ 1. Never log the full token
251
+ 2. Store tokens securely — note that `TokenStore` does not encrypt them; apply the opt-in [`Legate::Auth::Encryption`](./encryption) module yourself if at-rest encryption is required
252
+ 3. Implement proper token lifecycle management
253
+
254
+ ```ruby
255
+ # Example of secure logging
256
+ token = Legate::Auth::ExchangedCredential.new(
257
+ auth_type: :oauth2,
258
+ access_token: 'your-access-token',
259
+ refresh_token: 'your-refresh-token'
260
+ )
261
+
262
+ # Log safely (truncate sensitive values)
263
+ logger.info "Token type: #{token[:auth_type]}, " \
264
+ "Access token: #{token[:access_token].to_s[0..5]}..."
265
+ ```
266
+
267
+ ## See Also
268
+
269
+ - [Legate::Auth::Credential](./credential)
270
+ - [Legate::Auth::Scheme](./scheme)
271
+ - [Legate::Auth::TokenManager](./token_manager)
@@ -0,0 +1,175 @@
1
+ # Excon Middleware for Authentication
2
+
3
+ ## Overview
4
+
5
+ The `Legate::Auth::ExconMiddleware` provides automatic authentication header injection for HTTP requests made using the Excon HTTP client. This middleware simplifies authentication by seamlessly handling token lifecycle, automatic retries for authentication failures, and integrating with the Legate authentication system.
6
+
7
+ > **Wiring:** You normally don't construct this middleware directly or pass scheme/credential as top-level `Excon.new` keyword arguments. Instead use the helper methods `Legate::Auth.create_connection(url, scheme:, credential:, ...)` or `Legate::Auth.create_middleware(scheme:, credential:, ...)`. When the middleware runs inside Excon's stack it operates as a "shell" instance and reads its configuration from `datum[:connection].data[:auth_middleware_config]`, which the helpers set up for you.
8
+
9
+ ## Class Definition
10
+
11
+ ```ruby
12
+ module Legate
13
+ module Auth
14
+ class ExconMiddleware < Excon::Middleware::Base
15
+ # Implementation of Excon middleware for authentication
16
+ end
17
+ end
18
+ end
19
+ ```
20
+
21
+ ## Key Features
22
+
23
+ - Automatic injection of authentication headers based on scheme type
24
+ - Token refresh handling for expired credentials
25
+ - Configurable retry behavior for authentication failures
26
+ - Integration with the Legate token lifecycle management
27
+ - Support for all authentication schemes (API Key, Bearer, OAuth2, OIDC, Service Account)
28
+
29
+ ## Constructor
30
+
31
+ ### `initialize`
32
+
33
+ Creates a new ExconMiddleware instance.
34
+
35
+ **Parameters:**
36
+ - `stack` (Object): The Excon middleware stack (positional argument)
37
+ - `options` (Hash, optional): Configuration options (positional argument, default: {})
38
+
39
+ **Options Keys:**
40
+ - `:scheme` (Legate::Auth::Scheme): Authentication scheme to use
41
+ - `:credential` (Legate::Auth::Credential): Initial authentication credential
42
+ - `:token_store` (Legate::Auth::TokenStore): Store for caching tokens
43
+ - `:token_manager` (Legate::Auth::TokenManager): Token lifecycle manager
44
+ - `:auto_retry` (Boolean): Whether to automatically retry on auth failure
45
+ - `:max_retries` (Integer): Maximum number of retry attempts for auth failures (default: 3)
46
+ - `:backoff_strategy` (Symbol): Strategy for retry delay (`:none`, `:linear`, `:exponential`)
47
+ - `:backoff_factor` (Float): Factor for backoff calculation
48
+ - `:retry_non_idempotent` (Boolean): Whether to retry non-idempotent requests
49
+ - `:retry_on` (Array): HTTP status codes or exceptions that trigger retries
50
+
51
+ ## Instance Methods
52
+
53
+ ### `request_call`
54
+
55
+ Called before each request to inject authentication headers.
56
+
57
+ **Parameters:**
58
+ - `datum` (Hash): The Excon request datum
59
+
60
+ **Returns:**
61
+ - Hash: The modified request datum with authentication headers
62
+
63
+ ### `response_call`
64
+
65
+ Called after each response to check for authentication failures and handle retries.
66
+
67
+ **Parameters:**
68
+ - `datum` (Hash): The Excon response datum
69
+
70
+ **Returns:**
71
+ - Hash: The response datum
72
+
73
+ ### `should_retry?`
74
+
75
+ Determines if a request should be retried based on the response.
76
+
77
+ **Parameters:**
78
+ - `request_datum` (Hash): The original request datum
79
+ - `response_details` (Hash): Details about the response
80
+
81
+ **Returns:**
82
+ - Boolean: `true` if the request should be retried
83
+
84
+ ## Usage
85
+
86
+ ### Basic Usage
87
+
88
+ ```ruby
89
+ # Create a connection with authentication middleware via the helper
90
+ connection = Legate::Auth.create_connection('https://api.example.com',
91
+ scheme: api_key_scheme,
92
+ credential: api_key_credential
93
+ )
94
+
95
+ # Make authenticated requests
96
+ response = connection.get(path: '/protected-resource')
97
+ ```
98
+
99
+ ### With Token Store
100
+
101
+ ```ruby
102
+ # Pass a token store/manager for caching and lifecycle management
103
+ connection = Legate::Auth.create_connection('https://api.example.com',
104
+ scheme: oauth2_scheme,
105
+ credential: oauth2_credential,
106
+ token_store: token_store,
107
+ token_manager: token_manager
108
+ )
109
+ ```
110
+
111
+ ### With Retry Configuration
112
+
113
+ ```ruby
114
+ connection = Legate::Auth.create_connection('https://api.example.com',
115
+ scheme: scheme,
116
+ credential: credential,
117
+ auto_retry: true,
118
+ max_retries: 3,
119
+ backoff_strategy: :exponential,
120
+ backoff_factor: 2.0,
121
+ retry_on: [401, 403]
122
+ )
123
+ ```
124
+
125
+ These helpers add `ExconMiddleware` to the connection's middleware stack and store the configured middleware instance on `connection.data[:auth_middleware_config]`, where the shell middleware reads it at request time.
126
+
127
+ ## Example with OAuth2
128
+
129
+ ```ruby
130
+ # Create OAuth2 scheme and credential
131
+ scheme = Legate::Auth::Schemes::OAuth2.new(
132
+ token_url: 'https://auth.example.com/token',
133
+ authorization_url: 'https://auth.example.com/authorize',
134
+ scopes: ['read', 'write']
135
+ )
136
+ credential = Legate::Auth::Credential.new(
137
+ auth_type: :oauth2,
138
+ client_id: ENV['CLIENT_ID'],
139
+ client_secret: ENV['CLIENT_SECRET']
140
+ )
141
+
142
+ # Create connection with OAuth2 authentication
143
+ token_store = Legate::Auth::TokenStore.new(session_service)
144
+ token_manager = Legate::Auth::TokenManager.new(token_store)
145
+
146
+ connection = Legate::Auth.create_connection('https://api.example.com',
147
+ scheme: scheme,
148
+ credential: credential,
149
+ token_store: token_store,
150
+ token_manager: token_manager
151
+ )
152
+
153
+ # Make authenticated request
154
+ response = connection.get(path: '/user/profile')
155
+ ```
156
+
157
+ ## Middleware Stack Position
158
+
159
+ For proper operation, the `ExconMiddleware` should be positioned after any middleware that modifies the request parameters and before middleware that actually makes the HTTP request.
160
+
161
+ ## Integration with Token Lifecycle
162
+
163
+ The middleware automatically integrates with the Legate token lifecycle management:
164
+
165
+ 1. When a request is made, it checks for existing valid tokens
166
+ 2. If tokens are expired, it attempts to refresh them automatically
167
+ 3. If refresh fails or tokens are invalid, it triggers the appropriate authentication flow
168
+ 4. On successful authentication, it retries the original request
169
+
170
+ ## Related Classes
171
+
172
+ - [`Legate::Auth::Scheme`](./scheme): Base class for authentication schemes
173
+ - [`Legate::Auth::Credential`](./credential): Container for authentication credentials
174
+ - [`Legate::Auth::TokenManager`](./token_manager): Manages token lifecycle
175
+ - [`Legate::Auth::ToolContextExtension`](./tool_context_extension): Tool context integration
@@ -0,0 +1,30 @@
1
+ # Authentication API Reference
2
+
3
+ This section provides comprehensive documentation for all authentication-related classes and methods in the Legate Ruby library.
4
+
5
+ ## Core Classes
6
+
7
+ - [Legate::Auth::Scheme](./scheme) - Abstract base class for authentication schemes
8
+ - [Legate::Auth::Credential](./credential) - Container for authentication credentials
9
+ - [Legate::Auth::Config](./config) - Configuration for authentication flows
10
+ - [Legate::Auth::ExchangedCredential](./exchanged_credential) - Container for exchanged credentials
11
+
12
+ ## Authentication Schemes
13
+
14
+ - [Legate::Auth::Schemes::ApiKey](./schemes/api_key) - API Key authentication scheme
15
+ - [Legate::Auth::Schemes::HTTPBearer](./schemes/http_bearer) - HTTP Bearer authentication scheme
16
+ - [Legate::Auth::Schemes::OAuth2](./schemes/oauth2) - OAuth2 authentication scheme
17
+ - [Legate::Auth::Schemes::OpenIDConnect](./schemes/openid_connect) - OpenID Connect authentication scheme
18
+ - [Legate::Auth::Schemes::ServiceAccount](./schemes/service_account) - Service Account authentication scheme
19
+ - [Legate::Auth::Schemes::GoogleServiceAccount](./schemes/google_service_account) - Google Service Account authentication scheme
20
+
21
+ ## Authentication Management
22
+
23
+ - [Legate::Auth::TokenManager](./token_manager) - Token lifecycle management
24
+ - [Legate::Auth::TokenStore](./token_store) - Secure token storage
25
+ - [Legate::Auth::Encryption](./encryption) - Opt-in encryption utilities (not wired into TokenStore)
26
+
27
+ ## Integration
28
+
29
+ - [Legate::Auth::ToolContextExtension](./tool_context_extension) - Tool context authentication extensions
30
+ - [Legate::Auth::ExconMiddleware](./excon_middleware) - Middleware for Excon HTTP client