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,540 @@
1
+ # Environment Variable Management
2
+
3
+ This guide covers best practices and troubleshooting for environment variables used with the Legate Ruby library's authentication system.
4
+
5
+ ## Overview
6
+
7
+ The Legate Ruby library uses environment variables for storing sensitive credentials and configuration settings. This approach separates sensitive data from your code, improving security and making your application more portable across different environments.
8
+
9
+ ## Environment Variable Best Practices
10
+
11
+ ### Naming Conventions
12
+
13
+ Use consistent naming conventions for your environment variables:
14
+
15
+ ```ruby
16
+ # Preferred naming pattern
17
+ CLIENT_ID # General purpose
18
+ GOOGLE_CLIENT_ID # Provider-specific
19
+ DEV_CLIENT_ID # Environment-specific
20
+ DEV_GOOGLE_CLIENT_ID # Environment and provider-specific
21
+ ```
22
+
23
+ ### Security Considerations
24
+
25
+ 1. **Never Commit Environment Variables**:
26
+ ```bash
27
+ # Add environment files to .gitignore
28
+ echo ".env" >> .gitignore
29
+ echo ".env.*" >> .gitignore
30
+ ```
31
+
32
+ 2. **Use Different Values Across Environments**:
33
+ ```bash
34
+ # Development environment
35
+ export DEV_CLIENT_ID="dev-client-id"
36
+ export DEV_CLIENT_SECRET="dev-client-secret"
37
+
38
+ # Production environment
39
+ export PROD_CLIENT_ID="prod-client-id"
40
+ export PROD_CLIENT_SECRET="prod-client-secret"
41
+ ```
42
+
43
+ 3. **Limit Access to Environment Variables**:
44
+ ```bash
45
+ # Set restrictive permissions on environment files
46
+ chmod 600 .env
47
+ ```
48
+
49
+ ## Common Issues and Solutions
50
+
51
+ ### Missing Environment Variables
52
+
53
+ **Symptoms:**
54
+ - "Environment variable not found" errors
55
+ - Authentication failing with no clear error
56
+
57
+ **Possible Causes and Solutions:**
58
+
59
+ 1. **Environment File Not Loaded**
60
+ ```ruby
61
+ # Problem: .env file not loaded
62
+
63
+ # Solution: Use a library like dotenv
64
+ require 'dotenv'
65
+ Dotenv.load # Load .env file
66
+
67
+ # Or load environment-specific files
68
+ Dotenv.load(".env.#{ENV['RACK_ENV'] || 'development'}")
69
+ ```
70
+
71
+ 2. **Environment Variable Not Set in Current Shell**
72
+ ```bash
73
+ # Problem: Variable set in one shell but not available in another
74
+
75
+ # Solution: Verify the variable is set in the current shell
76
+ echo $CLIENT_ID
77
+
78
+ # If not set, set it:
79
+ export CLIENT_ID="your-client-id"
80
+
81
+ # Add to shell profile for persistence:
82
+ echo 'export CLIENT_ID="your-client-id"' >> ~/.bash_profile
83
+ ```
84
+
85
+ 3. **Environment Variables in Production**
86
+ ```ruby
87
+ # Problem: Environment variables not set in production environment
88
+
89
+ # Solution: Set environment variables at the system or container level
90
+
91
+ # For Heroku:
92
+ # heroku config:set CLIENT_ID=your-client-id
93
+
94
+ # For Docker:
95
+ # docker run -e CLIENT_ID=your-client-id -e CLIENT_SECRET=your-client-secret your-app
96
+ ```
97
+
98
+ ### Environment Variable Resolution
99
+
100
+ **Symptoms:**
101
+ - Authentication failing with credential errors
102
+ - Environment variables not being properly resolved
103
+
104
+ **Possible Causes and Solutions:**
105
+
106
+ 1. **Incorrect Reference Format**
107
+ ```ruby
108
+ # Problem: Incorrect environment variable reference format
109
+
110
+ # Solution: Use the correct 'ENV:' prefix
111
+
112
+ # Incorrect:
113
+ credential = Legate::Auth::Credential.new(
114
+ auth_type: :oauth2,
115
+ client_id: "$CLIENT_ID", # Wrong format
116
+ client_secret: "${CLIENT_SECRET}" # Wrong format
117
+ )
118
+
119
+ # Correct:
120
+ credential = Legate::Auth::Credential.new(
121
+ auth_type: :oauth2,
122
+ client_id: "ENV:CLIENT_ID", # Correct format
123
+ client_secret: "ENV:CLIENT_SECRET" # Correct format
124
+ )
125
+ ```
126
+
127
+ 2. **Case Sensitivity Issues**
128
+ ```ruby
129
+ # Problem: Environment variable case mismatch
130
+
131
+ # Solution: Use consistent case
132
+
133
+ # If environment variable is defined as:
134
+ # export CLIENT_ID="your-client-id"
135
+
136
+ # This won't work:
137
+ credential = Legate::Auth::Credential.new(
138
+ auth_type: :oauth2,
139
+ client_id: "ENV:client_id" # Wrong case
140
+ )
141
+
142
+ # This will work:
143
+ credential = Legate::Auth::Credential.new(
144
+ auth_type: :oauth2,
145
+ client_id: "ENV:CLIENT_ID" # Correct case
146
+ )
147
+ ```
148
+
149
+ 3. **Debug Environment Variable Resolution**
150
+ ```ruby
151
+ # To debug environment variable resolution:
152
+ def debug_env_var(name)
153
+ puts "Checking environment variable: #{name}"
154
+
155
+ if ENV[name]
156
+ puts "✓ Environment variable is set"
157
+ puts "Value length: #{ENV[name].length} characters"
158
+ puts "Value preview: #{ENV[name][0..5]}..." if ENV[name].length > 0
159
+ else
160
+ puts "✗ Environment variable is NOT set"
161
+ puts "Available env vars: #{ENV.keys.grep(/#{name}/i).join(', ')}"
162
+ end
163
+ end
164
+
165
+ # Usage:
166
+ debug_env_var('CLIENT_ID')
167
+ debug_env_var('CLIENT_SECRET')
168
+ ```
169
+
170
+ ### Service Account JSON in Environment Variables
171
+
172
+ **Symptoms:**
173
+ - JSON parsing errors with service account keys
174
+ - Malformed service account credentials
175
+
176
+ **Possible Causes and Solutions:**
177
+
178
+ 1. **Escaping Issues**
179
+ ```ruby
180
+ # Problem: JSON escaping issues in the environment variable
181
+
182
+ # Solution: Properly escape the JSON string
183
+
184
+ # Incorrect (newlines and quotes will cause issues):
185
+ # export SERVICE_ACCOUNT_JSON='{"private_key":"-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----\n"}'
186
+
187
+ # Better approach - base64 encode the JSON:
188
+ # 1. Encode the file to base64
189
+ base64_key=$(base64 -i service-account-key.json)
190
+
191
+ # 2. Set the environment variable with the base64 string
192
+ export SERVICE_ACCOUNT_JSON_BASE64="$base64_key"
193
+
194
+ # 3. In your code, decode the base64 string
195
+ require 'base64'
196
+ json_string = Base64.decode64(ENV['SERVICE_ACCOUNT_JSON_BASE64'])
197
+
198
+ credential = Legate::Auth::Credential.new(
199
+ auth_type: :service_account,
200
+ service_account_key: json_string # raw JSON string, not a parsed Hash
201
+ )
202
+ ```
203
+
204
+ 2. **Size Limitations**
205
+ ```ruby
206
+ # Problem: Environment variable too large
207
+
208
+ # Solution: Use a file-based approach instead
209
+
210
+ # Option 1: Store the service account key in a file
211
+ # This is often better for large service account keys
212
+
213
+ credential = Legate::Auth::Credential.new(
214
+ auth_type: :service_account,
215
+ service_account_key_file: 'path/to/service-account-key.json'
216
+ )
217
+
218
+ # Option 2: Use a secret management service
219
+ # Example with AWS Secrets Manager:
220
+ require 'aws-sdk-secretsmanager'
221
+
222
+ client = Aws::SecretsManager::Client.new(region: 'us-west-2')
223
+ secret = client.get_secret_value(secret_id: 'my-service-account-key')
224
+
225
+ credential = Legate::Auth::Credential.new(
226
+ auth_type: :service_account,
227
+ service_account_key: secret.secret_string # raw JSON string
228
+ )
229
+ ```
230
+
231
+ ### Environment Variable Loading Order
232
+
233
+ **Symptoms:**
234
+ - Unexpected environment variable values
235
+ - Environment variables overwritten unexpectedly
236
+
237
+ **Possible Causes and Solutions:**
238
+
239
+ 1. **Multiple Environment Files**
240
+ ```ruby
241
+ # Problem: Multiple environment files with conflicting variables
242
+
243
+ # Solution: Establish a clear loading order
244
+
245
+ # With dotenv, you can control the order:
246
+ require 'dotenv'
247
+
248
+ # Load in this order (later files override earlier ones):
249
+ Dotenv.load('.env.local.development') # Local development overrides
250
+ Dotenv.load('.env.development') # Environment-specific defaults
251
+ Dotenv.load('.env.local') # Local overrides
252
+ Dotenv.load('.env') # Default values
253
+ ```
254
+
255
+ 2. **Application Code Overwriting Environment Variables**
256
+ ```ruby
257
+ # Problem: Code overwrites environment variables
258
+
259
+ # Solution: Don't modify ENV directly, use a configuration layer
260
+
261
+ # Avoid this:
262
+ ENV['CLIENT_ID'] = 'hardcoded-value' # Don't do this!
263
+
264
+ # Better approach - use a configuration object:
265
+ class Configuration
266
+ def initialize
267
+ @values = {}
268
+ @values[:client_id] = ENV['CLIENT_ID']
269
+ end
270
+
271
+ def client_id
272
+ @values[:client_id]
273
+ end
274
+ end
275
+
276
+ config = Configuration.new
277
+ ```
278
+
279
+ ## Environment Variable Management Tools
280
+
281
+ ### Using dotenv for Development
282
+
283
+ ```ruby
284
+ # Install dotenv gem
285
+ # gem install dotenv
286
+
287
+ # Create a .env file in your project root
288
+ # CLIENT_ID=your-client-id
289
+ # CLIENT_SECRET=your-client-secret
290
+
291
+ # In your application:
292
+ require 'dotenv'
293
+ Dotenv.load
294
+
295
+ # Now ENV['CLIENT_ID'] is available
296
+ ```
297
+
298
+ ### Using Encrypted Environment Variables
299
+
300
+ ```ruby
301
+ # For sensitive production data, consider encrypted environment files
302
+ # Example using rails-encrypted-attributes:
303
+
304
+ # Install the gem
305
+ # gem install rails-encrypted-attributes
306
+
307
+ require 'rails-encrypted-attributes'
308
+
309
+ # Set up encryption
310
+ encryptor = RailsEncrypted::Encryptor.new(
311
+ key: ENV['ENCRYPTION_KEY'],
312
+ salt: 'legate-auth'
313
+ )
314
+
315
+ # Encrypt environment variable values
316
+ encrypted_value = encryptor.encrypt(ENV['CLIENT_SECRET'])
317
+ puts "Encrypted value: #{encrypted_value}"
318
+
319
+ # Decrypt when needed
320
+ decrypted_value = encryptor.decrypt(encrypted_value)
321
+ ```
322
+
323
+ ### Environment Variable Validation
324
+
325
+ Validate required environment variables at startup:
326
+
327
+ ```ruby
328
+ # Create an environment variable validator
329
+ class EnvironmentValidator
330
+ REQUIRED_VARIABLES = {
331
+ oauth2: ['CLIENT_ID', 'CLIENT_SECRET'],
332
+ api_key: ['API_KEY'],
333
+ service_account: ['SERVICE_ACCOUNT_JSON']
334
+ }
335
+
336
+ def self.validate!(auth_type)
337
+ required = REQUIRED_VARIABLES[auth_type.to_sym]
338
+ return unless required
339
+
340
+ missing = required.select { |var| ENV[var].nil? }
341
+ if missing.any?
342
+ raise "Missing required environment variables for #{auth_type}: #{missing.join(', ')}"
343
+ end
344
+ end
345
+ end
346
+
347
+ # Usage
348
+ auth_type = :oauth2
349
+ EnvironmentValidator.validate!(auth_type)
350
+ ```
351
+
352
+ ## Environment Variable Security
353
+
354
+ ### Protecting Environment Variables
355
+
356
+ Environment variables can be exposed in various ways. Protect them by:
357
+
358
+ 1. **Avoiding Debug Output**
359
+ ```ruby
360
+ # Don't log sensitive environment variables
361
+
362
+ # Avoid:
363
+ puts "ENV dump: #{ENV.inspect}"
364
+
365
+ # Instead, log only non-sensitive variables or mask sensitive ones:
366
+ def safe_env_dump
367
+ safe_env = ENV.to_h.dup
368
+ %w(CLIENT_SECRET API_KEY PRIVATE_KEY PASSWORD).each do |pattern|
369
+ safe_env.each do |key, value|
370
+ if key.include?(pattern)
371
+ safe_env[key] = "[REDACTED]"
372
+ end
373
+ end
374
+ end
375
+ safe_env
376
+ end
377
+
378
+ puts "Safe ENV dump: #{safe_env_dump.inspect}"
379
+ ```
380
+
381
+ 2. **Sanitizing Error Messages**
382
+ ```ruby
383
+ # Sanitize error messages that might contain environment variables
384
+
385
+ begin
386
+ # Some code that might raise an error with sensitive data
387
+ rescue => e
388
+ # Sanitize error message before logging
389
+ error_message = e.message
390
+ %w(CLIENT_SECRET API_KEY PRIVATE_KEY PASSWORD).each do |pattern|
391
+ ENV.each do |key, value|
392
+ if key.include?(pattern) && value && !value.empty?
393
+ error_message = error_message.gsub(value, "[REDACTED]")
394
+ end
395
+ end
396
+ end
397
+
398
+ logger.error "Error: #{error_message}"
399
+ end
400
+ ```
401
+
402
+ 3. **Restricting Environment Variable Access**
403
+ ```ruby
404
+ # Restrict access to environment variables using a wrapper
405
+
406
+ class SecureEnv
407
+ def self.get(name)
408
+ # Implement access control or auditing here
409
+ ENV[name]
410
+ end
411
+ end
412
+
413
+ # Usage
414
+ client_id = SecureEnv.get('CLIENT_ID')
415
+ ```
416
+
417
+ ## Provider-Specific Environment Variables
418
+
419
+ ### Google Cloud
420
+
421
+ ```bash
422
+ # Google OAuth2
423
+ export GOOGLE_CLIENT_ID="your-client-id"
424
+ export GOOGLE_CLIENT_SECRET="your-client-secret"
425
+
426
+ # Google Service Account
427
+ export GOOGLE_APPLICATION_CREDENTIALS="path/to/service-account-key.json"
428
+ ```
429
+
430
+ ### Microsoft Azure
431
+
432
+ ```bash
433
+ # Azure OAuth2/OIDC
434
+ export AZURE_CLIENT_ID="your-client-id"
435
+ export AZURE_CLIENT_SECRET="your-client-secret"
436
+ export AZURE_TENANT_ID="your-tenant-id"
437
+
438
+ # Azure Service Principal
439
+ export AZURE_SUBSCRIPTION_ID="your-subscription-id"
440
+ ```
441
+
442
+ ### AWS
443
+
444
+ ```bash
445
+ # AWS credentials
446
+ export AWS_ACCESS_KEY_ID="your-access-key-id"
447
+ export AWS_SECRET_ACCESS_KEY="your-secret-access-key"
448
+ export AWS_SESSION_TOKEN="your-session-token"
449
+ export AWS_REGION="us-west-2"
450
+ ```
451
+
452
+ ## Troubleshooting Tools
453
+
454
+ ### Environment Variable Inspector
455
+
456
+ Create a simple tool to inspect environment variables:
457
+
458
+ ```ruby
459
+ # Save this as env_inspector.rb
460
+ #!/usr/bin/env ruby
461
+
462
+ require 'optparse'
463
+
464
+ options = {}
465
+ OptionParser.new do |opts|
466
+ opts.banner = "Usage: env_inspector.rb [options]"
467
+
468
+ opts.on("-v", "--var NAME", "Check a specific environment variable") do |v|
469
+ options[:var] = v
470
+ end
471
+
472
+ opts.on("-p", "--pattern PATTERN", "Check variables matching a pattern") do |p|
473
+ options[:pattern] = p
474
+ end
475
+
476
+ opts.on("-l", "--list", "List all environment variables (values redacted)") do
477
+ options[:list] = true
478
+ end
479
+ end.parse!
480
+
481
+ if options[:var]
482
+ var = options[:var]
483
+ puts "Environment variable: #{var}"
484
+ if ENV[var]
485
+ puts " Value is set (#{ENV[var].length} characters)"
486
+ if var.upcase.include?("SECRET") || var.upcase.include?("KEY") || var.upcase.include?("PASSWORD")
487
+ puts " Value: [REDACTED]"
488
+ else
489
+ puts " Value: #{ENV[var]}"
490
+ end
491
+ else
492
+ puts " NOT SET"
493
+ similar = ENV.keys.select { |k| k.match(/#{var}/i) }
494
+ if similar.any?
495
+ puts " Similar variables: #{similar.join(', ')}"
496
+ end
497
+ end
498
+ elsif options[:pattern]
499
+ pattern = options[:pattern]
500
+ matches = ENV.keys.select { |k| k.match(/#{pattern}/i) }
501
+ puts "Variables matching pattern '#{pattern}':"
502
+ if matches.any?
503
+ matches.each do |var|
504
+ puts " #{var}: #{var.upcase.include?('SECRET') || var.upcase.include?('KEY') || var.upcase.include?('PASSWORD') ? '[REDACTED]' : ENV[var]}"
505
+ end
506
+ else
507
+ puts " No matches found"
508
+ end
509
+ elsif options[:list]
510
+ puts "All environment variables:"
511
+ ENV.each do |key, value|
512
+ if key.upcase.include?("SECRET") || key.upcase.include?("KEY") || key.upcase.include?("PASSWORD")
513
+ puts " #{key}: [REDACTED]"
514
+ else
515
+ puts " #{key}: #{value}"
516
+ end
517
+ end
518
+ else
519
+ puts "No options specified. Use --help for usage information."
520
+ end
521
+ ```
522
+
523
+ Usage:
524
+
525
+ ```bash
526
+ # Check a specific variable
527
+ ruby env_inspector.rb --var CLIENT_ID
528
+
529
+ # Check variables matching a pattern
530
+ ruby env_inspector.rb --pattern GOOGLE
531
+
532
+ # List all variables (with sensitive values redacted)
533
+ ruby env_inspector.rb --list
534
+ ```
535
+
536
+ ## Next Steps
537
+
538
+ - [Credential Storage Issues](./credential_storage): For issues with storing credentials
539
+ - [Token Lifecycle Management](../guides/token_lifecycle): Advanced token management techniques
540
+ - [OAuth2 Troubleshooting](./oauth2_issues): For OAuth2-specific authentication issues
@@ -0,0 +1,11 @@
1
+ # Authentication Troubleshooting
2
+
3
+ This section provides solutions to common authentication issues and best practices for debugging authentication flows.
4
+
5
+ ## Common Issues
6
+
7
+ - [OAuth2 Flow Issues](./oauth2_issues) - Solutions for OAuth2 authentication problems
8
+ - [OpenID Connect Issues](./oidc_issues) - Solutions for OIDC authentication problems
9
+ - [Token Refresh Problems](./token_refresh) - Solving token refresh and expiration issues
10
+ - [Credential Storage Issues](./credential_storage) - Solutions for credential storage problems
11
+ - [Environment Variable Issues](./environment_variables) - Resolving `ENV:`-prefixed credential values