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,190 @@
1
+ # API Key Authentication
2
+
3
+ API Keys are one of the simplest forms of authentication, commonly used for server-to-server API access. The Legate Ruby library provides comprehensive support for API Key authentication in various formats.
4
+
5
+ ## Overview
6
+
7
+ API Key authentication works by including a key in the request, typically in one of three locations:
8
+
9
+ - **Header**: The API key is added as an HTTP header (most common)
10
+ - **Query Parameter**: The API key is added to the URL query string
11
+ - **Cookie**: The API key is included in a cookie
12
+
13
+ ## Basic Setup
14
+
15
+ ### Session Service and Token Store
16
+
17
+ For enhanced functionality and token management, you can set up a session service and token store:
18
+
19
+ ```ruby
20
+ # Create session service for token storage
21
+ session_service = Legate::SessionService::InMemory.new
22
+
23
+ # Create a basic token store for caching
24
+ token_store = Legate::Auth::TokenStore.new(session_service)
25
+ ```
26
+
27
+ ### Creating an API Key Scheme
28
+
29
+ ```ruby
30
+ # Create an API Key scheme
31
+ scheme = Legate::Auth::Schemes::ApiKey.new
32
+ ```
33
+
34
+ ### Creating an API Key Credential
35
+
36
+ ```ruby
37
+ # Direct API key value
38
+ credential = Legate::Auth::Credential.new(
39
+ auth_type: :api_key,
40
+ api_key: 'your-api-key-value'
41
+ )
42
+
43
+ # API key from environment variable (recommended for security)
44
+ credential = Legate::Auth::Credential.new(
45
+ auth_type: :api_key,
46
+ api_key: ENV['API_KEY']
47
+ )
48
+
49
+ # With custom location and name (e.g., for query parameter)
50
+ credential = Legate::Auth::Credential.new(
51
+ auth_type: :api_key,
52
+ api_key: ENV['API_KEY'],
53
+ location: 'query', # Options: 'header', 'query', 'cookie'
54
+ name: 'api_key' # Parameter name in the chosen location
55
+ )
56
+ ```
57
+
58
+ ## Usage Examples
59
+
60
+ ### Connection Helper Approach
61
+
62
+ The most straightforward way to apply API key authentication is via the
63
+ connection helper, which attaches the key to every request:
64
+
65
+ ```ruby
66
+ # Create a credential with the API key
67
+ scheme = Legate::Auth::Schemes::ApiKey.new
68
+ credential = Legate::Auth::Credential.new(
69
+ auth_type: :api_key,
70
+ api_key: ENV['API_KEY'],
71
+ location: 'query',
72
+ name: 'api_key'
73
+ )
74
+
75
+ # Build an authenticated connection; the API key is applied automatically
76
+ connection = Legate::Auth.create_connection('https://api.example.com',
77
+ scheme: scheme,
78
+ credential: credential
79
+ )
80
+ response = connection.get(path: '/api/endpoint')
81
+ ```
82
+
83
+ Inside a tool, do the same within `perform_execution(params, context)` (see
84
+ [`ToolContextExtension`](../api_reference/tool_context_extension)).
85
+
86
+ ### Middleware Approach
87
+
88
+ For more direct HTTP client usage, you can use the Legate Auth middleware:
89
+
90
+ ```ruby
91
+ # Create a connection with API key middleware
92
+ connection = Legate::Auth.create_api_key_connection(
93
+ 'https://api.example.com',
94
+ api_key: ENV['API_KEY'],
95
+ location: 'query',
96
+ name: 'api_key',
97
+ token_store: token_store # Optional
98
+ )
99
+
100
+ # Make requests through the middleware
101
+ response = connection.request(
102
+ method: :get,
103
+ path: '/api/endpoint',
104
+ query: { param: 'value' }
105
+ )
106
+ ```
107
+
108
+ ### Manual Authentication Application
109
+
110
+ For cases where you need more control, you can manually apply authentication:
111
+
112
+ ```ruby
113
+ # Create a request hash
114
+ request = {
115
+ method: :get,
116
+ path: '/api/endpoint',
117
+ query: { param: 'value' },
118
+ headers: {}
119
+ }
120
+
121
+ # Apply authentication manually
122
+ request_with_auth = Legate::Auth::ToolIntegration.apply_authentication(
123
+ request,
124
+ scheme,
125
+ credential,
126
+ token_store # Optional
127
+ )
128
+
129
+ # Use the authenticated request with your HTTP client
130
+ connection = Excon.new('https://api.example.com')
131
+ response = connection.request(request_with_auth)
132
+ ```
133
+
134
+ ### Direct HTTP Client Usage
135
+
136
+ For the simplest cases, you can directly include the API key:
137
+
138
+ ```ruby
139
+ # Create connection
140
+ connection = Excon.new('https://api.example.com')
141
+
142
+ # Include API key in query parameters
143
+ response = connection.request(
144
+ method: :get,
145
+ path: '/api/endpoint',
146
+ query: {
147
+ api_key: ENV['API_KEY'],
148
+ param: 'value'
149
+ }
150
+ )
151
+ ```
152
+
153
+ ## API Key Security Best Practices
154
+
155
+ 1. **Environment Variables**: Store API keys in environment variables
156
+ 2. **Token Store**: Use token store for caching and management when appropriate
157
+ 3. **Secure Transport**: Always use HTTPS for API requests
158
+ 4. **Key Rotation**: Update API keys periodically
159
+ 5. **Minimal Permissions**: Use keys with the minimum required access
160
+
161
+ ## Troubleshooting
162
+
163
+ ### Common Issues
164
+
165
+ 1. **Authentication Failure**: Verify the API key location and name match the API requirements
166
+ 2. **Token Store Issues**: Ensure session service is properly initialized
167
+ 3. **Middleware Configuration**: Check connection parameters when using `create_api_key_connection`
168
+
169
+ ### Debugging Tips
170
+
171
+ ```ruby
172
+ # Debug authentication application
173
+ request = { headers: {}, query: {} }
174
+ modified_request = scheme.apply_to_request(request, credential)
175
+ puts "Modified request: #{modified_request.inspect}"
176
+
177
+ # For verbose auth logging, run with LEGATE_LOG_LEVEL=DEBUG
178
+ connection = Legate::Auth.create_api_key_connection(
179
+ 'https://api.example.com',
180
+ api_key: ENV['API_KEY'],
181
+ location: 'query',
182
+ name: 'api_key'
183
+ )
184
+ ```
185
+
186
+ ## Next Steps
187
+
188
+ - [Authentication Overview](./overview): Return to the overview of authentication
189
+ - [HTTP Bearer Authentication](./bearer): Learn about Bearer token authentication
190
+ - [OAuth2 Authentication](./oauth2): Implement OAuth2 authentication flows
@@ -0,0 +1,172 @@
1
+ # HTTP Bearer Authentication
2
+
3
+ ## Overview
4
+
5
+ HTTP Bearer authentication is a simple and widely used authentication scheme that involves sending a token, typically a JWT (JSON Web Token), in the `Authorization` header of HTTP requests. The Legate Ruby library provides built-in support for this authentication scheme through the `Legate::Auth::Schemes::HTTPBearer` class.
6
+
7
+ ## Key Concepts
8
+
9
+ - **Bearer Token**: A security token that grants access to protected resources, which the bearer can use without proving possession of a cryptographic key
10
+ - **Authorization Header**: HTTP header used to send the bearer token in the format `Authorization: Bearer <token>`
11
+ - **Token Types**: Commonly a JWT, but can be any opaque string accepted by the API
12
+
13
+ ## Setting Up Bearer Authentication
14
+
15
+ ### Step 1: Create the Authentication Scheme
16
+
17
+ ```ruby
18
+ # Create an HTTP Bearer scheme
19
+ bearer_scheme = Legate::Auth::Schemes::HTTPBearer.new
20
+ ```
21
+
22
+ ### Step 2: Create the Credential
23
+
24
+ ```ruby
25
+ # Option 1: Directly provide the token
26
+ credential = Legate::Auth::Credential.new(
27
+ auth_type: :http_bearer,
28
+ bearer_token: 'your_bearer_token_here'
29
+ )
30
+
31
+ # Option 2: Read the token from an environment variable at runtime
32
+ credential = Legate::Auth::Credential.new(
33
+ auth_type: :http_bearer,
34
+ bearer_token: ENV['API_BEARER_TOKEN']
35
+ )
36
+
37
+ # Option 3: Reference an environment variable with the ENV: prefix (resolved lazily)
38
+ credential = Legate::Auth::Credential.new(
39
+ auth_type: :http_bearer,
40
+ bearer_token: 'ENV:API_BEARER_TOKEN'
41
+ )
42
+ ```
43
+
44
+ ### Step 3: Attach Bearer Authentication to a Connection
45
+
46
+ ```ruby
47
+ # Create an authenticated Excon connection using the helper
48
+ connection = Legate::Auth.create_connection('https://api.example.com',
49
+ scheme: bearer_scheme,
50
+ credential: credential
51
+ )
52
+
53
+ # The Authorization header is applied automatically
54
+ response = connection.get(path: '/protected-resource')
55
+ ```
56
+
57
+ ## Using Bearer Authentication in API Requests
58
+
59
+ ### Reading the token from a credential
60
+
61
+ You can read the bearer token from a credential using the `[]` accessor
62
+ (which resolves `ENV:` references):
63
+
64
+ ```ruby
65
+ bearer_token = credential[:bearer_token]
66
+
67
+ conn = Excon.new('https://api.example.com')
68
+ response = conn.get(
69
+ path: '/protected-resource',
70
+ headers: { 'Authorization' => "Bearer #{bearer_token}" }
71
+ )
72
+
73
+ JSON.parse(response.body)
74
+ ```
75
+
76
+ ### Using the Excon Middleware
77
+
78
+ You can also build the middleware explicitly and attach it via the connection helper:
79
+
80
+ ```ruby
81
+ # Create middleware for Bearer authentication
82
+ middleware = Legate::Auth.create_middleware(
83
+ scheme: bearer_scheme,
84
+ credential: credential
85
+ )
86
+ # (create_middleware returns a configured ExconMiddleware instance; the
87
+ # connection helpers below wire it onto a connection for you.)
88
+ ```
89
+
90
+ Or use the connection helper directly:
91
+
92
+ ```ruby
93
+ # Create an authenticated connection directly
94
+ connection = Legate::Auth.create_connection(
95
+ 'https://api.example.com',
96
+ scheme: bearer_scheme,
97
+ credential: credential
98
+ )
99
+
100
+ # Make authenticated requests
101
+ response = connection.get(path: '/protected-resource')
102
+ ```
103
+
104
+ ## Token Management
105
+
106
+ Unlike OAuth2 or OIDC, HTTP Bearer authentication does not include built-in token refresh mechanisms. If your bearer token expires, you will need to obtain a new one externally and update your credential:
107
+
108
+ ```ruby
109
+ # Update the bearer token on the credential
110
+ credential[:bearer_token] = new_token
111
+
112
+ # Or, if you reference it via 'ENV:API_BEARER_TOKEN', update the env var
113
+ ENV['API_BEARER_TOKEN'] = new_token
114
+ ```
115
+
116
+ ## Security Considerations
117
+
118
+ - Bearer tokens should be treated as sensitive information, similar to passwords
119
+ - Use HTTPS for all requests to prevent token interception
120
+ - Store tokens securely, preferably in environment variables rather than in code
121
+ - Use short-lived tokens where possible to minimize risk of token compromise
122
+ - Consider using OAuth2 or OIDC if you need more advanced features like token refresh and revocation
123
+
124
+ ## Complete Example
125
+
126
+ Here's a complete example of using Bearer authentication with the Legate:
127
+
128
+ ```ruby
129
+ require 'legate'
130
+ require 'excon'
131
+
132
+ # Create the scheme and credential
133
+ bearer_scheme = Legate::Auth::Schemes::HTTPBearer.new
134
+ credential = Legate::Auth::Credential.new(
135
+ auth_type: :http_bearer,
136
+ bearer_token: 'ENV:API_BEARER_TOKEN'
137
+ )
138
+
139
+ # Create a custom tool
140
+ class UserProfileTool < Legate::Tool
141
+ tool_description 'Gets the current user profile'
142
+
143
+ def perform_execution(params, context)
144
+ # Create an authenticated connection
145
+ bearer_scheme = Legate::Auth::Schemes::HTTPBearer.new
146
+ credential = Legate::Auth::Credential.new(
147
+ auth_type: :http_bearer,
148
+ bearer_token: 'ENV:API_BEARER_TOKEN'
149
+ )
150
+
151
+ connection = Legate::Auth.create_connection(
152
+ 'https://api.example.com',
153
+ scheme: bearer_scheme,
154
+ credential: credential
155
+ )
156
+
157
+ # Make the authenticated request
158
+ response = connection.get(path: '/user/profile')
159
+
160
+ # Check for authentication errors
161
+ if response.status == 401
162
+ { status: :error, error_message: 'Authentication failed. Bearer token may be invalid or expired.' }
163
+ else
164
+ { status: :success, result: JSON.parse(response.body) }
165
+ end
166
+ end
167
+ end
168
+ ```
169
+
170
+ ## Related Topics
171
+ - [Legate::Auth::Schemes::HTTPBearer API Reference](../api_reference/schemes/http_bearer)
172
+ - [Excon Middleware for Authentication](../api_reference/excon_middleware)
@@ -0,0 +1,255 @@
1
+ # Authentication Configuration
2
+
3
+ ## Overview
4
+
5
+ This guide explains how to configure authentication in your Legate Ruby applications. Proper configuration is essential for successfully authenticating with external APIs and services.
6
+
7
+ ## Configuration Components
8
+
9
+ Authentication in the Legate Ruby library involves configuring three main components:
10
+
11
+ 1. **Authentication Scheme**: Defines how the API expects authentication (API Key, OAuth2, etc.)
12
+ 2. **Authentication Credential**: Contains the initial information needed for authentication
13
+ 3. **Tool Configuration**: Associates schemes and credentials with tools
14
+
15
+ ## Authentication Schemes
16
+
17
+ Authentication schemes define the protocol and parameters for authenticating with an API.
18
+
19
+ ### Available Schemes
20
+
21
+ ```ruby
22
+ # API Key scheme (no constructor arguments — the key's location and name
23
+ # come from the credential at apply time)
24
+ api_key_scheme = Legate::Auth::Schemes::ApiKey.new
25
+
26
+ # HTTP Bearer scheme
27
+ bearer_scheme = Legate::Auth::Schemes::HTTPBearer.new
28
+
29
+ # OAuth2 scheme
30
+ oauth2_scheme = Legate::Auth::Schemes::OAuth2.new(
31
+ authorization_url: 'https://auth.example.com/authorize',
32
+ token_url: 'https://auth.example.com/token',
33
+ scopes: ['read', 'write']
34
+ )
35
+
36
+ # OpenID Connect scheme
37
+ oidc_scheme = Legate::Auth::Schemes::OpenIDConnect.new(
38
+ discovery_url: 'https://auth.example.com/.well-known/openid-configuration',
39
+ scopes: ['openid', 'profile', 'email']
40
+ )
41
+
42
+ # Service Account scheme
43
+ service_account_scheme = Legate::Auth::Schemes::ServiceAccount.new(
44
+ token_url: 'https://auth.example.com/token'
45
+ )
46
+
47
+ # Google Service Account scheme
48
+ google_service_account_scheme = Legate::Auth::Schemes::GoogleServiceAccount.new(
49
+ scopes: ['https://www.googleapis.com/auth/drive']
50
+ )
51
+ ```
52
+
53
+ ### Scheme Properties
54
+
55
+ Each scheme type has different configuration properties:
56
+
57
+ #### ApiKey Scheme
58
+
59
+ `ApiKey.new` takes **no constructor arguments**. The API key's location and name are read from the **credential** at apply time:
60
+
61
+ | Credential attribute | Description | Default |
62
+ |----------------------|-------------|---------|
63
+ | `location` | Location of the API key (`'header'`, `'query'`, `'cookie'`) | `'header'` |
64
+ | `name` | Header/parameter/cookie name | `'X-API-Key'` |
65
+
66
+ #### HTTPBearer Scheme
67
+
68
+ The HTTPBearer scheme doesn't require any additional configuration properties.
69
+
70
+ #### OAuth2 Scheme (constructor keyword arguments)
71
+
72
+ | Argument | Description | Default | Required |
73
+ |----------|-------------|---------|----------|
74
+ | `authorization_url` | Authorization endpoint URL | None | Yes (for interactive flows) |
75
+ | `token_url` | Token endpoint URL | None | Yes |
76
+ | `scopes` | List/space-string of OAuth2 scopes | [] | No |
77
+ | `use_pkce` | Whether to use PKCE | `true` | No |
78
+ | `additional_params` | Extra params for the authorization request | None | No |
79
+ | `revocation_url` | Token revocation endpoint URL | None | No |
80
+
81
+ #### OpenIDConnect Scheme (constructor keyword arguments)
82
+
83
+ Inherits all OAuth2 arguments, plus:
84
+
85
+ | Argument | Description | Default | Required |
86
+ |----------|-------------|---------|----------|
87
+ | `discovery_url` | OIDC discovery document URL | None | No (if endpoints given) |
88
+ | `jwks_url` | JSON Web Key Set URL | None | No |
89
+ | `userinfo_url` | UserInfo endpoint URL | None | No |
90
+ | `issuer` | Expected issuer | None | No |
91
+
92
+ #### ServiceAccount Scheme (constructor keyword arguments)
93
+
94
+ | Argument | Description | Default | Required |
95
+ |----------|-------------|---------|----------|
96
+ | `token_url` | Token endpoint URL | None | Yes |
97
+ | `audience` | Service account token audience | None | No |
98
+ | `scopes` | Requested scopes | [] | No |
99
+ | `token_lifetime` | JWT lifetime in seconds | 3600 | No |
100
+
101
+ #### GoogleServiceAccount Scheme (constructor keyword arguments)
102
+
103
+ | Argument | Description | Default | Required |
104
+ |----------|-------------|---------|----------|
105
+ | `scopes` | List of Google API scopes | None | No |
106
+ | `token_url` | Token endpoint URL | 'https://oauth2.googleapis.com/token' | No |
107
+ | `audience` | Service account token audience | token_url | No |
108
+ | `token_lifetime` | JWT lifetime in seconds | 3600 | No |
109
+
110
+ ## Authentication Credentials
111
+
112
+ Authentication credentials contain the initial information needed to start authentication.
113
+
114
+ ### Creating Credentials
115
+
116
+ Every credential requires an `auth_type:`.
117
+
118
+ ```ruby
119
+ # API Key credential
120
+ api_key_credential = Legate::Auth::Credential.new(
121
+ auth_type: :api_key,
122
+ api_key: ENV['API_KEY']
123
+ )
124
+
125
+ # HTTP Bearer credential
126
+ bearer_credential = Legate::Auth::Credential.new(
127
+ auth_type: :http_bearer,
128
+ bearer_token: ENV['BEARER_TOKEN']
129
+ )
130
+
131
+ # OAuth2 credential
132
+ oauth2_credential = Legate::Auth::Credential.new(
133
+ auth_type: :oauth2,
134
+ client_id: ENV['OAUTH2_CLIENT_ID'],
135
+ client_secret: ENV['OAUTH2_CLIENT_SECRET']
136
+ )
137
+
138
+ # Service Account credential (service_account_key is a raw JSON string)
139
+ service_account_credential = Legate::Auth::Credential.new(
140
+ auth_type: :service_account,
141
+ service_account_key: File.read('service-account.json')
142
+ )
143
+
144
+ # Google Service Account credential
145
+ google_service_account_credential = Legate::Auth::Credential.new(
146
+ auth_type: :google_service_account,
147
+ service_account_key: ENV['GOOGLE_SERVICE_ACCOUNT_JSON'] # raw JSON string
148
+ )
149
+ ```
150
+
151
+ ### Environment Variable References
152
+
153
+ The only mechanism for referencing environment variables is the `ENV:` prefix
154
+ inside a string value. There are no `*_env` attributes.
155
+
156
+ ```ruby
157
+ # Reference environment variables with the ENV: prefix
158
+ oauth2_credential = Legate::Auth::Credential.new(
159
+ auth_type: :oauth2,
160
+ client_id: 'ENV:OAUTH2_CLIENT_ID',
161
+ client_secret: 'ENV:OAUTH2_CLIENT_SECRET'
162
+ )
163
+ ```
164
+
165
+ ### Common Credential Properties
166
+
167
+ | Property | Description | Used With |
168
+ |----------|-------------|-----------|
169
+ | `auth_type` | Required: `:api_key`, `:http_bearer`, `:oauth2`, `:oidc`, `:service_account`, `:google_service_account`, `:basic` | All |
170
+ | `api_key` | The API key value (use `'ENV:NAME'` to read from the environment) | API Key scheme |
171
+ | `location` | API key location: `'header'`, `'query'`, or `'cookie'` | API Key scheme |
172
+ | `name` | API key header/parameter/cookie name | API Key scheme |
173
+ | `bearer_token` | The bearer token value | Bearer scheme |
174
+ | `client_id` | OAuth2/OIDC client ID | OAuth2, OIDC schemes |
175
+ | `client_secret` | OAuth2/OIDC client secret | OAuth2, OIDC schemes |
176
+ | `service_account_key` | Service account JSON as a raw string (use `'ENV:NAME'` to read from the environment) | Service Account schemes |
177
+ | `service_account_key_file` | Path to a file containing the service account JSON | Service Account schemes |
178
+
179
+ ## Using Authentication in Tools
180
+
181
+ Within a `Legate::Tool`, use the authentication helpers added to the
182
+ `ToolContext` (see [`ToolContextExtension`](../api_reference/tool_context_extension)):
183
+
184
+ ```ruby
185
+ class MyApiTool < Legate::Tool
186
+ tool_description 'A tool that interacts with an authenticated API'
187
+
188
+ def perform_execution(params, context)
189
+ context.with_authentication do
190
+ connection = Legate::Auth.create_connection('https://api.example.com',
191
+ scheme: oauth2_scheme,
192
+ credential: oauth2_credential
193
+ )
194
+ response = connection.get(path: '/resource')
195
+ { status: :success, result: response.body }
196
+ end
197
+ end
198
+ end
199
+ ```
200
+
201
+ ## Advanced Configuration
202
+
203
+ ### Token Store Configuration
204
+
205
+ Configure the token store and manager (both take **positional** arguments):
206
+
207
+ ```ruby
208
+ # Create a token store (positional session service)
209
+ token_store = Legate::Auth::TokenStore.new(session_service)
210
+
211
+ # Configure a token manager with the token store. Config is a positional Hash;
212
+ # the key is refresh_buffer (seconds before expiry to refresh), not refresh_threshold.
213
+ token_manager = Legate::Auth::TokenManager.new(token_store, {
214
+ refresh_buffer: 300 # Refresh tokens 5 minutes before expiration
215
+ })
216
+ ```
217
+
218
+ ### HTTP Client Configuration
219
+
220
+ The simplest way to attach authentication to an Excon connection is the
221
+ connection helper, which wires up the middleware for you:
222
+
223
+ ```ruby
224
+ # Create an authenticated connection directly
225
+ connection = Legate::Auth.create_connection(
226
+ 'https://api.example.com',
227
+ scheme: oauth2_scheme,
228
+ credential: oauth2_credential,
229
+ token_store: token_store,
230
+ max_retries: 3,
231
+ backoff_strategy: :exponential
232
+ )
233
+ ```
234
+
235
+ `Legate::Auth.create_middleware(scheme:, credential:, ...)` is also available
236
+ if you need to build the middleware instance yourself.
237
+
238
+ ## Configuration Best Practices
239
+
240
+ 1. **Use Environment Variables for Sensitive Values**: Always use environment variables for sensitive credentials like API keys, client secrets, and tokens
241
+ 2. **Validate Configuration**: Verify your authentication configuration before making API requests
242
+ 3. **Use HTTPS**: Always use HTTPS URLs for authentication endpoints
243
+ 4. **Limit Scopes**: Request only the scopes your application needs
244
+ 5. **Secure Storage**: Tokens are cached as plaintext in scoped state; apply the opt-in `Legate::Auth::Encryption` module yourself if you need at-rest encryption
245
+ 6. **Token Lifecycle**: Configure an appropriate `refresh_buffer` on the `TokenManager`
246
+ 7. **Error Handling**: Implement proper error handling for authentication failures
247
+
248
+ ## Related Topics
249
+ - [API Key Authentication](./api_key)
250
+ - [HTTP Bearer Authentication](./bearer)
251
+ - [OAuth2 Authentication](./oauth2)
252
+ - [OpenID Connect](./oidc)
253
+ - [Service Account Authentication](./service_account)
254
+ - [Token Lifecycle Management](./token_lifecycle)
255
+ - [Secure Credential Storage](./secure_storage)