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,250 @@
1
+ # Legate::Auth::Scheme
2
+
3
+ The `Scheme` class serves as the abstract base class for all authentication schemes in the Legate Ruby library. It defines the interface and common functionality that all authentication schemes must implement.
4
+
5
+ ## Overview
6
+
7
+ Authentication schemes represent different methods of authenticating API requests, such as API keys, OAuth2, OpenID Connect, or service accounts. The `Scheme` class provides a consistent interface for all these authentication methods, enabling the Legate to work with different authentication mechanisms in a unified way.
8
+
9
+ ## Class Methods
10
+
11
+ ### `new`
12
+
13
+ Creates a new instance of the authentication scheme.
14
+
15
+ **Parameters:**
16
+ - `kwargs` (Hash): Parameters specific to the authentication scheme
17
+
18
+ **Examples:**
19
+
20
+ ```ruby
21
+ # This is an abstract class and shouldn't be instantiated directly
22
+ # Instead, use one of the concrete implementations:
23
+ scheme = Legate::Auth::Schemes::ApiKey.new
24
+ ```
25
+
26
+ ## Instance Methods
27
+
28
+ ### `scheme_type`
29
+
30
+ Returns the type of the authentication scheme. This method must be implemented by concrete subclasses.
31
+
32
+ **Returns:**
33
+ - Symbol: The authentication scheme type (e.g., `:api_key`, `:oauth2`)
34
+
35
+ **Examples:**
36
+
37
+ ```ruby
38
+ scheme = Legate::Auth::Schemes::ApiKey.new
39
+ scheme.scheme_type # => :api_key
40
+ ```
41
+
42
+ ### `apply_to_request`
43
+
44
+ Applies authentication to a request based on the provided credential. This method must be implemented by concrete subclasses.
45
+
46
+ **Parameters:**
47
+ - `request` (Hash): The request to authenticate
48
+ - `credential` (Legate::Auth::ExchangedCredential): The credential to use for authentication
49
+
50
+ **Returns:**
51
+ - Hash: The modified request with authentication applied
52
+
53
+ **Examples:**
54
+
55
+ ```ruby
56
+ # This method is called internally by the Legate
57
+ # The implementation depends on the specific scheme
58
+ ```
59
+
60
+ ### `supports_refresh?`
61
+
62
+ Returns whether this scheme supports token refresh.
63
+
64
+ **Returns:**
65
+ - Boolean: `true` if the scheme supports token refresh
66
+
67
+ **Examples:**
68
+
69
+ ```ruby
70
+ scheme = Legate::Auth::Schemes::OAuth2.new(token_url: 'https://example.com/token')
71
+ scheme.supports_refresh? # => true (if refresh is supported)
72
+ ```
73
+
74
+ ### `exchange_token`
75
+
76
+ Exchanges a credential for an authentication token. This method must be implemented by concrete subclasses that support token exchange.
77
+
78
+ **Parameters:**
79
+ - `credential` (Legate::Auth::Credential): The credential to exchange
80
+
81
+ **Returns:**
82
+ - Legate::Auth::ExchangedCredential: The exchanged token
83
+
84
+ **Examples:**
85
+
86
+ ```ruby
87
+ # This method is called internally by the Legate
88
+ # The implementation depends on the specific scheme
89
+ ```
90
+
91
+ ### `refresh_token`
92
+
93
+ Refreshes an expired token. This method must be implemented by concrete subclasses that support token refresh.
94
+
95
+ **Parameters:**
96
+ - `token` (Legate::Auth::ExchangedCredential): The token to refresh
97
+ - `credential` (Legate::Auth::Credential): The original credential
98
+
99
+ **Returns:**
100
+ - Legate::Auth::ExchangedCredential: The refreshed token
101
+
102
+ **Examples:**
103
+
104
+ ```ruby
105
+ # This method is called internally by the Legate
106
+ # The implementation depends on the specific scheme
107
+ ```
108
+
109
+ ### `revoke_token`
110
+
111
+ Revokes a token. This method must be implemented by concrete subclasses that support token revocation.
112
+
113
+ **Parameters:**
114
+ - `token` (Legate::Auth::ExchangedCredential): The token to revoke
115
+ - `credential` (Legate::Auth::Credential): The original credential
116
+
117
+ **Examples:**
118
+
119
+ ```ruby
120
+ # This method is called internally by the Legate
121
+ # The implementation depends on the specific scheme
122
+ ```
123
+
124
+ ### `validate!`
125
+
126
+ Validates the scheme configuration. Raises an error if the configuration is invalid.
127
+
128
+ **Raises:**
129
+ - `Legate::Auth::SchemeValidationError`: If the scheme configuration is invalid
130
+
131
+ **Examples:**
132
+
133
+ ```ruby
134
+ scheme = Legate::Auth::Schemes::OAuth2.new(
135
+ authorization_url: 'https://example.com/authorize',
136
+ token_url: 'https://example.com/token'
137
+ )
138
+ scheme.validate! # Raises if configuration is incomplete
139
+ ```
140
+
141
+ ### `build_authorization_uri`
142
+
143
+ Builds an authorization URI for interactive authentication flows. This method must be implemented by concrete subclasses that support interactive authentication.
144
+
145
+ **Parameters:**
146
+ - `config` (Legate::Auth::Config): The authentication configuration
147
+ - `redirect_uri` (String, optional): The redirect URI for the authentication flow
148
+ - `state` (String, optional): The state parameter for CSRF protection
149
+
150
+ **Returns:**
151
+ - String: The authorization URI
152
+
153
+ **Examples:**
154
+
155
+ ```ruby
156
+ # This method is called internally by the Legate
157
+ # The implementation depends on the specific scheme
158
+ ```
159
+
160
+ ### `authentication_error?`
161
+
162
+ Checks if an HTTP response indicates an authentication error.
163
+
164
+ **Parameters:**
165
+ - `response` (Object): The HTTP response to check
166
+
167
+ **Returns:**
168
+ - Boolean: `true` if the response indicates an authentication error
169
+
170
+ **Examples:**
171
+
172
+ ```ruby
173
+ # This method is called internally by the Legate
174
+ # Used by ExconMiddleware to detect auth failures for retry
175
+ ```
176
+
177
+ ### `to_h`
178
+
179
+ Converts the scheme to a hash representation.
180
+
181
+ **Returns:**
182
+ - Hash: A hash representation of the scheme
183
+
184
+ ### `to_s`
185
+
186
+ Returns a string representation of the scheme.
187
+
188
+ **Returns:**
189
+ - String: A string representation of the scheme
190
+
191
+ ## Authentication Flow Types
192
+
193
+ The `Scheme` class supports different types of authentication flows:
194
+
195
+ 1. **Non-Interactive Authentication**:
196
+ - Direct authentication using API keys or bearer tokens
197
+ - No user interaction required
198
+ - Implemented by schemes like `ApiKey` and `HTTPBearer`
199
+
200
+ 2. **Token-Based Authentication**:
201
+ - Uses tokens for authentication
202
+ - May include token exchange, refresh, and revocation
203
+ - Implemented by schemes like `OAuth2`, `OpenIDConnect`, and `ServiceAccount`
204
+
205
+ 3. **Interactive Authentication**:
206
+ - Requires user interaction to complete authentication
207
+ - Uses `build_authorization_uri` for generating the auth URI
208
+ - Implemented by schemes like `OAuth2` and `OpenIDConnect`
209
+
210
+ ## Concrete Implementations
211
+
212
+ The Legate Ruby library includes the following concrete implementations of `Scheme`:
213
+
214
+ - [Legate::Auth::Schemes::ApiKey](./schemes/api_key): For API key authentication
215
+ - [Legate::Auth::Schemes::HTTPBearer](./schemes/http_bearer): For HTTP Bearer token authentication
216
+ - [Legate::Auth::Schemes::OAuth2](./schemes/oauth2): For OAuth2 authentication
217
+ - [Legate::Auth::Schemes::OpenIDConnect](./schemes/openid_connect): For OpenID Connect authentication
218
+ - [Legate::Auth::Schemes::ServiceAccount](./schemes/service_account): For service account authentication
219
+
220
+ ## Extension Points
221
+
222
+ To create a custom authentication scheme, extend the `Scheme` class and implement the required methods:
223
+
224
+ ```ruby
225
+ class CustomScheme < Legate::Auth::Scheme
226
+ def scheme_type
227
+ :custom
228
+ end
229
+
230
+ def apply_to_request(request, credential)
231
+ request[:headers] ||= {}
232
+ request[:headers]['Authorization'] = "Custom #{credential[:access_token]}"
233
+ request
234
+ end
235
+
236
+ def exchange_token(credential)
237
+ Legate::Auth::ExchangedCredential.new(
238
+ auth_type: :custom,
239
+ access_token: credential[:custom_token]
240
+ )
241
+ end
242
+ end
243
+ ```
244
+
245
+ ## See Also
246
+
247
+ - [Legate::Auth::Credential](./credential)
248
+ - [Legate::Auth::ExchangedCredential](./exchanged_credential)
249
+ - [Legate::Auth::Config](./config)
250
+ - [Legate::Auth::TokenManager](./token_manager)
@@ -0,0 +1,175 @@
1
+ # Legate::Auth::Schemes::ApiKey
2
+
3
+ The `ApiKey` class implements API key authentication, one of the simplest and most common methods for authenticating API requests. This scheme handles the inclusion of API keys in requests via headers, query parameters, or other methods.
4
+
5
+ ## Overview
6
+
7
+ API key authentication is a straightforward authentication method where a single secret key is included in API requests. The API key scheme in Legate Ruby provides flexible options for configuring how and where the API key is included in requests.
8
+
9
+ ## Class Methods
10
+
11
+ ### `new`
12
+
13
+ Creates a new API key authentication scheme. The constructor takes **no arguments** — the API key's location (`header`, `query`, or `cookie`) and parameter/header name are read from the **credential** at apply time (via its `location:` and `name:` attributes), not from the scheme.
14
+
15
+ **Examples:**
16
+
17
+ ```ruby
18
+ # Create an API key scheme (no constructor arguments)
19
+ scheme = Legate::Auth::Schemes::ApiKey.new
20
+
21
+ # Location and name live on the credential, not the scheme:
22
+ credential = Legate::Auth::Credential.new(
23
+ auth_type: :api_key,
24
+ api_key: 'my-api-key',
25
+ location: 'header', # 'header' (default), 'query', or 'cookie'
26
+ name: 'X-API-Key' # header/parameter/cookie name (default: 'X-API-Key')
27
+ )
28
+ ```
29
+
30
+ ## Instance Methods
31
+
32
+ ### `scheme_type`
33
+
34
+ Returns the type of the authentication scheme.
35
+
36
+ **Returns:**
37
+ - Symbol: `:api_key`
38
+
39
+ **Examples:**
40
+
41
+ ```ruby
42
+ scheme = Legate::Auth::Schemes::ApiKey.new
43
+ scheme.scheme_type # => :api_key
44
+ ```
45
+
46
+ ### `apply_to_request`
47
+
48
+ Applies API key authentication to a request by adding the API key to the appropriate location.
49
+
50
+ **Parameters:**
51
+ - `request` (Hash): The request to authenticate
52
+ - `credential` (Legate::Auth::ExchangedCredential): The exchanged credential containing the API key
53
+
54
+ **Returns:**
55
+ - Hash: The authenticated request with the API key in the specified location
56
+
57
+ **Examples:**
58
+
59
+ ```ruby
60
+ # Create an API key credential and exchange it
61
+ credential = Legate::Auth::Credential.new(
62
+ auth_type: :api_key,
63
+ api_key: 'my-api-key'
64
+ )
65
+
66
+ scheme = Legate::Auth::Schemes::ApiKey.new
67
+ token = scheme.exchange_token(credential)
68
+
69
+ # Apply to a request
70
+ request = { headers: {} }
71
+ authenticated = scheme.apply_to_request(request, token)
72
+ ```
73
+
74
+ ### `exchange_token`
75
+
76
+ Exchanges a credential for an authentication token. For API keys, this simply wraps the API key in an ExchangedCredential.
77
+
78
+ **Parameters:**
79
+ - `credential` (Legate::Auth::Credential): The credential to exchange
80
+
81
+ **Returns:**
82
+ - Legate::Auth::ExchangedCredential: The exchanged token
83
+
84
+ **Examples:**
85
+
86
+ ```ruby
87
+ # Create an API key credential
88
+ credential = Legate::Auth::Credential.new(
89
+ auth_type: :api_key,
90
+ api_key: 'my-api-key'
91
+ )
92
+
93
+ # Exchange for a token
94
+ scheme = Legate::Auth::Schemes::ApiKey.new
95
+ token = scheme.exchange_token(credential)
96
+
97
+ # The exchanged credential stores the key under :api_key (not :access_token)
98
+ puts token[:api_key] # => "my-api-key"
99
+ puts token[:access_token] # => nil
100
+ ```
101
+
102
+ ### `to_h`
103
+
104
+ Converts the scheme to a hash representation.
105
+
106
+ **Returns:**
107
+ - Hash: A hash representation of the scheme configuration
108
+
109
+ ## Usage Examples
110
+
111
+ ### Basic API Key Authentication
112
+
113
+ ```ruby
114
+ # Create an API key scheme
115
+ scheme = Legate::Auth::Schemes::ApiKey.new
116
+
117
+ # Create a credential with the API key
118
+ credential = Legate::Auth::Credential.new(
119
+ auth_type: :api_key,
120
+ api_key: 'my-api-key'
121
+ )
122
+
123
+ # Exchange for a token
124
+ token = scheme.exchange_token(credential)
125
+
126
+ # Apply to a request
127
+ request = { headers: {} }
128
+ authenticated = scheme.apply_to_request(request, token)
129
+ ```
130
+
131
+ ### With Token Manager
132
+
133
+ ```ruby
134
+ # Create an API key scheme
135
+ scheme = Legate::Auth::Schemes::ApiKey.new
136
+
137
+ # Create a credential with the API key
138
+ credential = Legate::Auth::Credential.new(
139
+ auth_type: :api_key,
140
+ api_key: 'my-api-key'
141
+ )
142
+
143
+ # Use with token manager
144
+ token_store = Legate::Auth::TokenStore.new(session_service)
145
+ token_manager = Legate::Auth::TokenManager.new(token_store)
146
+
147
+ # Get a token (this will create and store the ExchangedCredential)
148
+ token = token_manager.get_token(scheme, credential)
149
+ ```
150
+
151
+ ### With Environment Variables
152
+
153
+ ```ruby
154
+ # Create a credential with the API key from an environment variable
155
+ credential = Legate::Auth::Credential.new(
156
+ auth_type: :api_key,
157
+ api_key: 'ENV:API_KEY'
158
+ )
159
+ ```
160
+
161
+ ## Security Considerations
162
+
163
+ - API keys are essentially long-term passwords and should be protected accordingly
164
+ - Always use HTTPS for all API requests that include API keys
165
+ - Restrict API key permissions to only what's necessary
166
+ - Implement proper access controls for API keys
167
+ - Rotate API keys regularly
168
+ - Consider using more advanced authentication schemes (OAuth2, OIDC) for sensitive operations
169
+
170
+ ## See Also
171
+
172
+ - [Legate::Auth::Credential](../credential)
173
+ - [Legate::Auth::ExchangedCredential](../exchanged_credential)
174
+ - [Legate::Auth::Scheme](../scheme)
175
+ - [Legate::Auth::TokenManager](../token_manager)
@@ -0,0 +1,221 @@
1
+ # Legate::Auth::Schemes::GoogleServiceAccount
2
+
3
+ The `GoogleServiceAccount` class implements Google-specific service account authentication. It extends the base `ServiceAccount` class with Google Cloud-specific functionality for authenticating with Google APIs.
4
+
5
+ ## Overview
6
+
7
+ Google Service Account authentication uses a key-based approach where a signed JWT (JSON Web Token) is exchanged for an access token from Google's authentication servers. This scheme is specifically optimized for Google Cloud APIs, handling the proper audience, token URLs, and other Google-specific configuration details.
8
+
9
+ ## Class Methods
10
+
11
+ ### `new`
12
+
13
+ Creates a new Google Service Account authentication scheme.
14
+
15
+ **Parameters:**
16
+ - `scopes` (Array<String>, optional): The Google API scopes to request access for
17
+ - `kwargs` (Hash, optional): Additional parameters for the authentication scheme (inherits ServiceAccount params)
18
+
19
+ **Examples:**
20
+
21
+ ```ruby
22
+ # Basic Google Service Account scheme with scopes
23
+ scheme = Legate::Auth::Schemes::GoogleServiceAccount.new(
24
+ scopes: ['https://www.googleapis.com/auth/cloud-platform']
25
+ )
26
+
27
+ # With additional options
28
+ scheme = Legate::Auth::Schemes::GoogleServiceAccount.new(
29
+ scopes: [
30
+ 'https://www.googleapis.com/auth/cloud-platform',
31
+ 'https://www.googleapis.com/auth/bigquery'
32
+ ],
33
+ token_lifetime: 3600
34
+ )
35
+ ```
36
+
37
+ ## Instance Methods
38
+
39
+ ### `scheme_type`
40
+
41
+ Returns the type of the authentication scheme.
42
+
43
+ **Returns:**
44
+ - Symbol: `:google_service_account`
45
+
46
+ **Examples:**
47
+
48
+ ```ruby
49
+ scheme = Legate::Auth::Schemes::GoogleServiceAccount.new
50
+ scheme.scheme_type # => :google_service_account
51
+ ```
52
+
53
+ ### `validate!`
54
+
55
+ Validates the scheme configuration for Google service account authentication.
56
+
57
+ **Raises:**
58
+ - `Legate::Auth::SchemeValidationError`: If the scheme configuration is invalid
59
+
60
+ ### `apply_to_request`
61
+
62
+ Applies Google service account authentication to a request by adding the access token to the Authorization header.
63
+
64
+ **Parameters:**
65
+ - `request` (Hash): The request to authenticate
66
+ - `credential` (Legate::Auth::ExchangedCredential): The exchanged credential containing the access token
67
+
68
+ **Returns:**
69
+ - Hash: The authenticated request with access token in the Authorization header
70
+
71
+ **Examples:**
72
+
73
+ ```ruby
74
+ request = { headers: {} }
75
+ authenticated = scheme.apply_to_request(request, exchanged_credential)
76
+ puts authenticated[:headers]['Authorization'] # => "Bearer [access-token]"
77
+ ```
78
+
79
+ ### `exchange_token`
80
+
81
+ Exchanges a Google service account credential for an access token by creating and signing a JWT and exchanging it with Google's token endpoint.
82
+
83
+ **Parameters:**
84
+ - `credential` (Legate::Auth::Credential): The credential containing the service account information
85
+
86
+ **Returns:**
87
+ - Legate::Auth::ExchangedCredential: The exchanged token
88
+
89
+ **Examples:**
90
+
91
+ ```ruby
92
+ # Create a service account credential
93
+ credential = Legate::Auth::Credential.new(
94
+ auth_type: :google_service_account,
95
+ service_account_key: File.read('google-service-account.json') # raw JSON string, not a parsed Hash
96
+ )
97
+
98
+ # Exchange for a token
99
+ scheme = Legate::Auth::Schemes::GoogleServiceAccount.new(
100
+ scopes: ['https://www.googleapis.com/auth/cloud-platform']
101
+ )
102
+ token = scheme.exchange_token(credential)
103
+
104
+ puts token[:access_token] # => "[google-access-token]"
105
+ ```
106
+
107
+ ### `refresh_token`
108
+
109
+ Refreshes an expired Google service account token by performing a new token exchange.
110
+
111
+ **Parameters:**
112
+ - `token` (Legate::Auth::ExchangedCredential): The token to refresh
113
+ - `credential` (Legate::Auth::Credential): The original credential
114
+
115
+ **Returns:**
116
+ - Legate::Auth::ExchangedCredential: The refreshed token
117
+
118
+ **Examples:**
119
+
120
+ ```ruby
121
+ refreshed_token = scheme.refresh_token(expired_token, credential)
122
+ ```
123
+
124
+ ## Usage Examples
125
+
126
+ ### Basic Authentication Flow
127
+
128
+ ```ruby
129
+ # Create a Google Service Account scheme
130
+ scheme = Legate::Auth::Schemes::GoogleServiceAccount.new(
131
+ scopes: [
132
+ 'https://www.googleapis.com/auth/cloud-platform',
133
+ 'https://www.googleapis.com/auth/bigquery'
134
+ ]
135
+ )
136
+
137
+ # Create a credential from a service account key file
138
+ credential = Legate::Auth::Credential.new(
139
+ auth_type: :google_service_account,
140
+ service_account_key: File.read('google-service-account.json') # raw JSON string, not a parsed Hash
141
+ )
142
+
143
+ # Exchange the credential for a token
144
+ token = scheme.exchange_token(credential)
145
+
146
+ # Apply to a request
147
+ request = { headers: {} }
148
+ authenticated = scheme.apply_to_request(request, token)
149
+ puts authenticated[:headers]['Authorization'] # => "Bearer [access-token]"
150
+ ```
151
+
152
+ ### With Token Manager
153
+
154
+ ```ruby
155
+ # Create a Google Service Account scheme
156
+ scheme = Legate::Auth::Schemes::GoogleServiceAccount.new(
157
+ scopes: ['https://www.googleapis.com/auth/cloud-platform']
158
+ )
159
+
160
+ # Create a credential from a service account key file
161
+ credential = Legate::Auth::Credential.new(
162
+ auth_type: :google_service_account,
163
+ service_account_key: File.read('google-service-account.json') # raw JSON string, not a parsed Hash
164
+ )
165
+
166
+ # Use with token manager for automatic token management
167
+ token_store = Legate::Auth::TokenStore.new(session_service)
168
+ token_manager = Legate::Auth::TokenManager.new(token_store)
169
+
170
+ # Get a token (this will create, store, and refresh the token as needed)
171
+ token = token_manager.get_token(scheme, credential)
172
+ ```
173
+
174
+ ### Using a Key File from Path
175
+
176
+ ```ruby
177
+ # Point the credential at a service account key file on disk
178
+ credential = Legate::Auth::Credential.new(
179
+ auth_type: :google_service_account,
180
+ service_account_key_file: '/path/to/google-service-account.json'
181
+ )
182
+
183
+ # Create the scheme and use as normal
184
+ scheme = Legate::Auth::Schemes::GoogleServiceAccount.new(
185
+ scopes: ['https://www.googleapis.com/auth/cloud-platform']
186
+ )
187
+
188
+ # Exchange for a token
189
+ token = scheme.exchange_token(credential)
190
+ ```
191
+
192
+ > **Note:** Application Default Credentials (ADC) are not supported. Provide credentials explicitly via `service_account_key` (a raw JSON string) or `service_account_key_file` (a path).
193
+
194
+ ## Google API Scopes
195
+
196
+ Common Google API scopes include:
197
+
198
+ | API | Scope |
199
+ |-----|-------|
200
+ | Google Cloud Platform (all services) | `https://www.googleapis.com/auth/cloud-platform` |
201
+ | BigQuery | `https://www.googleapis.com/auth/bigquery` |
202
+ | Cloud Storage | `https://www.googleapis.com/auth/devstorage.read_write` |
203
+ | Compute Engine | `https://www.googleapis.com/auth/compute` |
204
+ | Google Drive | `https://www.googleapis.com/auth/drive` |
205
+ | Gmail | `https://www.googleapis.com/auth/gmail.send` |
206
+ | Google Sheets | `https://www.googleapis.com/auth/spreadsheets` |
207
+
208
+ ## Security Considerations
209
+
210
+ - Store service account keys securely and restrict access
211
+ - Grant service accounts the minimum necessary permissions
212
+ - Regularly rotate service account keys (Google recommends every 90 days)
213
+ - Monitor service account usage for suspicious activity
214
+ - Consider using IAM Conditions to restrict service account usage based on source IP, time, etc.
215
+
216
+ ## See Also
217
+
218
+ - [Legate::Auth::Schemes::ServiceAccount](./service_account)
219
+ - [Legate::Auth::Credential](../credential)
220
+ - [Legate::Auth::ExchangedCredential](../exchanged_credential)
221
+ - [Legate::Auth::TokenManager](../token_manager)