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,259 @@
1
+ / File: lib/legate/web/views/auth_schemes.slim
2
+ .content.mb-6
3
+ nav.breadcrumb(aria-label="breadcrumbs")
4
+ ul
5
+ li
6
+ a(href="/auth") Authentication
7
+ li.is-active
8
+ a(href="/auth/schemes" aria-current="page") Schemes
9
+
10
+ h1.title.is-2 Authentication Schemes
11
+ p.subtitle.is-4 Manage authentication schemes available to Legate agents
12
+
13
+ .buttons.mb-4
14
+ button.button.is-primary#add-scheme-btn
15
+ span.icon
16
+ i.fas.fa-plus
17
+ span Add New Scheme
18
+
19
+ - if @schemes && @schemes.any?
20
+ .columns.is-multiline
21
+ - @schemes.each do |scheme|
22
+ .column.is-one-third
23
+ .card
24
+ .card-content
25
+ .media
26
+ .media-left
27
+ span.icon.is-large.has-text-primary
28
+ - case scheme[:scheme_type]
29
+ - when :api_key
30
+ i.fas.fa-key.fa-2x
31
+ - when :oauth2
32
+ i.fas.fa-shield-alt.fa-2x
33
+ - when :oidc, :openid_connect
34
+ i.fas.fa-id-badge.fa-2x
35
+ - when :service_account, :google_service_account
36
+ i.fas.fa-robot.fa-2x
37
+ - when :http_bearer
38
+ i.fas.fa-ticket-alt.fa-2x
39
+ - else
40
+ i.fas.fa-question.fa-2x
41
+ .media-content
42
+ p.title.is-5 = scheme[:name]
43
+ p.subtitle.is-6 = scheme[:class_name]
44
+ .content
45
+ p = scheme[:description]
46
+ .level.is-mobile.mt-3
47
+ .level-left
48
+ .level-item
49
+ .tags
50
+ span.tag.is-info.is-light = scheme[:scheme_type]
51
+ - if scheme[:has_config]
52
+ span.tag.is-warning.is-light
53
+ span.icon.is-small
54
+ i.fas.fa-cog
55
+ span Configurable
56
+ .level-right
57
+ .level-item
58
+ .buttons.are-small
59
+ a.button.is-primary.is-outlined(href="/auth/schemes/#{scheme[:name]}")
60
+ span.icon.is-small
61
+ i.fas.fa-eye
62
+ span Details
63
+
64
+ .content.is-small.mt-3
65
+ .columns.is-mobile.is-gapless
66
+ .column
67
+ .has-text-centered
68
+ p.heading Compatible Credentials
69
+ p.title.is-6 = scheme[:compatible_credentials_count]
70
+ .column
71
+ .has-text-centered
72
+ p.heading URL Mappings
73
+ p.title.is-6 = scheme[:url_mappings_count]
74
+
75
+ - else
76
+ .columns.is-centered
77
+ .column.is-half
78
+ .notification.is-info
79
+ h3.title.is-4 No Authentication Schemes
80
+ p No authentication schemes are currently registered.
81
+ p This is unexpected as the authentication manager should register default schemes.
82
+
83
+ .content.mt-6
84
+ h2.title.is-4 Available Scheme Types
85
+ .columns
86
+ .column.is-half
87
+ .content
88
+ h3.title.is-5
89
+ span.icon.has-text-primary
90
+ i.fas.fa-key
91
+ span API Key
92
+ p Simple authentication using API keys sent in headers or query parameters. Best for services that provide API keys.
93
+
94
+ h3.title.is-5.mt-4
95
+ span.icon.has-text-primary
96
+ i.fas.fa-ticket-alt
97
+ span HTTP Bearer
98
+ p Bearer token authentication and basic HTTP authentication. Commonly used for RESTful APIs.
99
+
100
+ .column.is-half
101
+ .content
102
+ h3.title.is-5
103
+ span.icon.has-text-primary
104
+ i.fas.fa-shield-alt
105
+ span OAuth2
106
+ p OAuth2 authorization code flow for secure third-party authentication. Used by services like GitHub, Google, etc.
107
+
108
+ h3.title.is-5.mt-4
109
+ span.icon.has-text-primary
110
+ i.fas.fa-robot
111
+ span Service Account
112
+ p Service account authentication for automated systems. Includes Google Cloud service accounts with JSON keys.
113
+
114
+ /! Add New Scheme Modal
115
+ #add-scheme-modal.modal
116
+ .modal-background
117
+ .modal-card
118
+ header.modal-card-head
119
+ p.modal-card-title Add New Authentication Scheme
120
+ button.delete(aria-label="close")
121
+ section.modal-card-body
122
+ form#add-scheme-form
123
+ .field
124
+ label.label Scheme Type
125
+ .control
126
+ .select.is-fullwidth
127
+ select#scheme-type-select(name="scheme_type" required)
128
+ option(value="") Select scheme type...
129
+ option(value="api_key") API Key
130
+ option(value="http_bearer") HTTP Bearer
131
+ option(value="oauth2") OAuth2
132
+ option(value="oidc") OpenID Connect
133
+ option(value="service_account") Service Account
134
+ option(value="google_service_account") Google Service Account
135
+
136
+ .field
137
+ label.label Scheme Name
138
+ .control
139
+ input.input(type="text" name="scheme_name" placeholder="Enter unique scheme name" required)
140
+ p.help Give this scheme instance a unique name (e.g., "github_oauth", "api_key_prod")
141
+
142
+ #scheme-config-fields
143
+ /! Dynamic configuration fields will be inserted here
144
+
145
+ footer.modal-card-foot
146
+ button.button.is-primary(type="submit" form="add-scheme-form") Add Scheme
147
+ button.button Cancel
148
+
149
+ javascript:
150
+ document.addEventListener('DOMContentLoaded', function() {
151
+ const addSchemeBtn = document.getElementById('add-scheme-btn');
152
+ const addSchemeModal = document.getElementById('add-scheme-modal');
153
+ const schemeTypeSelect = document.getElementById('scheme-type-select');
154
+ const schemeConfigFields = document.getElementById('scheme-config-fields');
155
+ const addSchemeForm = document.getElementById('add-scheme-form');
156
+
157
+ // Scheme configuration templates
158
+ const schemeConfigs = {
159
+ oauth2: [
160
+ { name: 'authorization_url', type: 'url', required: true, label: 'Authorization URL', placeholder: 'https://example.com/oauth/authorize' },
161
+ { name: 'token_url', type: 'url', required: true, label: 'Token URL', placeholder: 'https://example.com/oauth/token' },
162
+ { name: 'scopes', type: 'text', required: false, label: 'Scopes (space-separated)', placeholder: 'read write' },
163
+ { name: 'use_pkce', type: 'checkbox', required: false, label: 'Use PKCE', checked: true },
164
+ { name: 'revocation_url', type: 'url', required: false, label: 'Revocation URL', placeholder: 'https://example.com/oauth/revoke' }
165
+ ],
166
+ oidc: [
167
+ { name: 'authorization_url', type: 'url', required: true, label: 'Authorization URL', placeholder: 'https://example.com/oidc/authorize' },
168
+ { name: 'token_url', type: 'url', required: true, label: 'Token URL', placeholder: 'https://example.com/oidc/token' },
169
+ { name: 'userinfo_url', type: 'url', required: false, label: 'UserInfo URL', placeholder: 'https://example.com/oidc/userinfo' },
170
+ { name: 'scopes', type: 'text', required: false, label: 'Scopes (space-separated)', placeholder: 'openid profile email' },
171
+ { name: 'use_pkce', type: 'checkbox', required: false, label: 'Use PKCE', checked: true }
172
+ ],
173
+ service_account: [
174
+ { name: 'token_url', type: 'url', required: true, label: 'Token URL', placeholder: 'https://example.com/token' },
175
+ { name: 'scopes', type: 'text', required: false, label: 'Scopes (space-separated)', placeholder: 'read write' }
176
+ ],
177
+ google_service_account: [
178
+ { name: 'scopes', type: 'text', required: false, label: 'Scopes (space-separated)', placeholder: 'https://www.googleapis.com/auth/cloud-platform' }
179
+ ]
180
+ };
181
+
182
+ // Show modal
183
+ addSchemeBtn.addEventListener('click', function() {
184
+ addSchemeModal.classList.add('is-active');
185
+ });
186
+
187
+ // Hide modal
188
+ function hideModal() {
189
+ addSchemeModal.classList.remove('is-active');
190
+ addSchemeForm.reset();
191
+ schemeConfigFields.innerHTML = '';
192
+ }
193
+
194
+ addSchemeModal.querySelectorAll('.modal-background, .delete, .button:not(.is-primary)').forEach(function(element) {
195
+ element.addEventListener('click', hideModal);
196
+ });
197
+
198
+ // Update configuration fields when scheme type changes
199
+ schemeTypeSelect.addEventListener('change', function() {
200
+ const schemeType = this.value;
201
+ schemeConfigFields.innerHTML = '';
202
+
203
+ if (schemeConfigs[schemeType]) {
204
+ schemeConfigs[schemeType].forEach(function(field) {
205
+ const fieldDiv = document.createElement('div');
206
+ fieldDiv.className = 'field';
207
+
208
+ let fieldHTML = `<label class="label">${field.label}</label><div class="control">`;
209
+
210
+ if (field.type === 'checkbox') {
211
+ fieldHTML += `<label class="checkbox">
212
+ <input type="checkbox" name="${field.name}" ${field.checked ? 'checked' : ''}>
213
+ ${field.label}
214
+ </label>`;
215
+ } else {
216
+ fieldHTML += `<input class="input" type="${field.type}" name="${field.name}"
217
+ placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''}>`;
218
+ }
219
+
220
+ fieldHTML += '</div>';
221
+ fieldDiv.innerHTML = fieldHTML;
222
+ schemeConfigFields.appendChild(fieldDiv);
223
+ });
224
+ }
225
+ });
226
+
227
+ // Handle form submission
228
+ addSchemeForm.addEventListener('submit', function(e) {
229
+ e.preventDefault();
230
+
231
+ const formData = new FormData(this);
232
+
233
+ fetch('/auth/schemes', {
234
+ method: 'POST',
235
+ body: formData
236
+ })
237
+ .then(response => response.json())
238
+ .then(data => {
239
+ if (data.success) {
240
+ hideModal();
241
+ if (typeof showToast === 'function') {
242
+ showToast(data.message, 'is-success');
243
+ }
244
+ // Reload the page to show the new scheme
245
+ window.location.reload();
246
+ } else {
247
+ if (typeof showToast === 'function') {
248
+ showToast(data.error || 'Failed to add scheme', 'is-danger');
249
+ }
250
+ }
251
+ })
252
+ .catch(error => {
253
+ console.error('Error:', error);
254
+ if (typeof showToast === 'function') {
255
+ showToast('Network error occurred', 'is-danger');
256
+ }
257
+ });
258
+ });
259
+ });
@@ -0,0 +1,418 @@
1
+ nav.breadcrumb aria-label="breadcrumbs"
2
+ ul
3
+ li
4
+ a href="/auth" Authentication
5
+ li.is-active
6
+ a href="/auth/test" aria-current="page" Testing
7
+
8
+ .section
9
+ .container
10
+ .columns
11
+ .column.is-12
12
+ h1.title.is-2 Authentication Testing Dashboard
13
+ p.subtitle Test and validate your authentication configurations
14
+
15
+ .columns
16
+ .column.is-4
17
+ .card
18
+ .card-header
19
+ .card-header-title
20
+ span.icon.has-text-primary
21
+ i.fas.fa-key
22
+ | &nbsp; Credential Testing
23
+ .card-content
24
+ p.content Test individual credentials to verify they're properly configured and functional.
25
+ .field
26
+ label.label Select Credential
27
+ .control
28
+ .select.is-fullwidth
29
+ select#credential-select
30
+ option value="" Select a credential...
31
+ - @credentials.each do |credential|
32
+ option value=credential[:name] data-type=credential[:auth_type]
33
+ = credential[:name]
34
+ | (
35
+ = credential[:auth_type]
36
+ | )
37
+ .field
38
+ label.label Test URL (Optional)
39
+ .control
40
+ input.input#credential-test-url type="url" placeholder="https://api.example.com/test"
41
+ p.help For API Key and Bearer Token credentials, provide a test endpoint
42
+ .field
43
+ .control
44
+ button.button.is-primary.is-fullwidth#test-credential-btn disabled=true Test Credential
45
+ .card-footer
46
+ .card-footer-item
47
+ #credential-test-results
48
+
49
+ .column.is-4
50
+ .card
51
+ .card-header
52
+ .card-header-title
53
+ span.icon.has-text-primary
54
+ i.fas.fa-shield-alt
55
+ | &nbsp; Scheme Testing
56
+ .card-content
57
+ p.content Validate authentication schemes and their configurations.
58
+ .field
59
+ label.label Select Scheme
60
+ .control
61
+ .select.is-fullwidth
62
+ select#scheme-select
63
+ option value="" Select a scheme...
64
+ - @schemes.each do |scheme|
65
+ option value=scheme[:name] data-type=scheme[:scheme_type]
66
+ = scheme[:name]
67
+ | (
68
+ = scheme[:scheme_type]
69
+ | )
70
+ .field
71
+ .control
72
+ button.button.is-primary.is-fullwidth#test-scheme-btn disabled=true Test Scheme
73
+ .card-footer
74
+ .card-footer-item
75
+ #scheme-test-results
76
+
77
+ .column.is-4
78
+ .card
79
+ .card-header
80
+ .card-header-title
81
+ span.icon.has-text-primary
82
+ i.fas.fa-exchange-alt
83
+ | &nbsp; Flow Testing
84
+ .card-content
85
+ p.content Simulate complete authentication flows to verify end-to-end functionality.
86
+ .field
87
+ label.label Select Scheme
88
+ .control
89
+ .select.is-fullwidth
90
+ select#flow-scheme-select
91
+ option value="" Select a scheme...
92
+ - @schemes.each do |scheme|
93
+ option value=scheme[:name] data-type=scheme[:scheme_type]
94
+ = scheme[:name]
95
+ | (
96
+ = scheme[:scheme_type]
97
+ | )
98
+ .field
99
+ label.label Select Credential
100
+ .control
101
+ .select.is-fullwidth
102
+ select#flow-credential-select disabled=true
103
+ option value="" Select a credential...
104
+ .field
105
+ .control
106
+ button.button.is-primary.is-fullwidth#test-flow-btn disabled=true Test Flow
107
+ .card-footer
108
+ .card-footer-item
109
+ #flow-test-results
110
+
111
+ .columns
112
+ .column.is-12
113
+ .card
114
+ .card-header
115
+ .card-header-title
116
+ span.icon.has-text-primary
117
+ i.fas.fa-globe
118
+ | &nbsp; API Call Testing
119
+ .card-content
120
+ p.content Test actual API calls using configured authentication to verify real-world functionality.
121
+ .columns
122
+ .column.is-4
123
+ .field
124
+ label.label API URL
125
+ .control
126
+ input.input#api-test-url type="url" placeholder="https://api.example.com/endpoint" required=true
127
+ p.help The API endpoint to test against
128
+ .column.is-4
129
+ .field
130
+ label.label Authentication Scheme
131
+ .control
132
+ .select.is-fullwidth
133
+ select#api-scheme-select
134
+ option value="" Select a scheme...
135
+ - @schemes.each do |scheme|
136
+ option value=scheme[:name] data-type=scheme[:scheme_type]
137
+ = scheme[:name]
138
+ | (
139
+ = scheme[:scheme_type]
140
+ | )
141
+ .column.is-4
142
+ .field
143
+ label.label Credential
144
+ .control
145
+ .select.is-fullwidth
146
+ select#api-credential-select disabled=true
147
+ option value="" Select a credential...
148
+ .field
149
+ .control
150
+ button.button.is-primary.is-fullwidth#test-api-btn disabled=true Test API Call
151
+ .card-footer
152
+ .card-footer-item
153
+ #api-test-results
154
+
155
+ .columns
156
+ .column.is-12
157
+ .card
158
+ .card-header
159
+ .card-header-title
160
+ span.icon.has-text-primary
161
+ i.fas.fa-chart-line
162
+ | &nbsp; Testing Summary
163
+ .card-content
164
+ .columns
165
+ .column.is-3.has-text-centered
166
+ p.heading Schemes Available
167
+ p.title.is-4 = @schemes.size
168
+ .column.is-3.has-text-centered
169
+ p.heading Credentials Available
170
+ p.title.is-4 = @credentials.size
171
+ .column.is-3.has-text-centered
172
+ p.heading URL Mappings
173
+ p.title.is-4 = @mappings_count
174
+ .column.is-3.has-text-centered
175
+ p.heading Test Status
176
+ p.title.is-4#overall-status Ready
177
+
178
+ javascript:
179
+ document.addEventListener('DOMContentLoaded', function() {
180
+ // Credential testing
181
+ const credentialSelect = document.getElementById('credential-select');
182
+ const credentialTestBtn = document.getElementById('test-credential-btn');
183
+ const credentialTestUrl = document.getElementById('credential-test-url');
184
+ const credentialResults = document.getElementById('credential-test-results');
185
+
186
+ credentialSelect.addEventListener('change', function() {
187
+ credentialTestBtn.disabled = !this.value;
188
+ });
189
+
190
+ credentialTestBtn.addEventListener('click', function() {
191
+ const credentialName = credentialSelect.value;
192
+ const testUrl = credentialTestUrl.value;
193
+
194
+ if (!credentialName) return;
195
+
196
+ this.classList.add('is-loading');
197
+ credentialResults.innerHTML = '';
198
+
199
+ const formData = new FormData();
200
+ if (testUrl) formData.append('test_url', testUrl);
201
+
202
+ Legate.apiRequest(`/auth/test/credential/${credentialName}`, { method: 'POST', body: formData })
203
+ .then(data => {
204
+ this.classList.remove('is-loading');
205
+ displayCredentialResults(data);
206
+ })
207
+ .catch(error => {
208
+ this.classList.remove('is-loading');
209
+ Legate.renderError(credentialResults, error.message);
210
+ });
211
+ });
212
+
213
+ function displayCredentialResults(data) {
214
+ let html = `<div class="notification ${data.success ? 'is-success' : 'is-danger'}">
215
+ <strong>Credential: ${escapeHtml(data.credential_name)}</strong><br>
216
+ Overall Status: ${data.success ? 'PASSED' : 'FAILED'}
217
+ </div>`;
218
+
219
+ html += Legate.renderTestItems(data.tests);
220
+
221
+ credentialResults.innerHTML = html;
222
+ }
223
+
224
+ // Scheme testing
225
+ const schemeSelect = document.getElementById('scheme-select');
226
+ const schemeTestBtn = document.getElementById('test-scheme-btn');
227
+ const schemeResults = document.getElementById('scheme-test-results');
228
+
229
+ schemeSelect.addEventListener('change', function() {
230
+ schemeTestBtn.disabled = !this.value;
231
+ });
232
+
233
+ schemeTestBtn.addEventListener('click', function() {
234
+ const schemeName = schemeSelect.value;
235
+
236
+ if (!schemeName) return;
237
+
238
+ this.classList.add('is-loading');
239
+ schemeResults.innerHTML = '';
240
+
241
+ Legate.apiRequest(`/auth/test/scheme/${schemeName}`, { method: 'POST' })
242
+ .then(data => {
243
+ this.classList.remove('is-loading');
244
+ displaySchemeResults(data);
245
+ })
246
+ .catch(error => {
247
+ this.classList.remove('is-loading');
248
+ Legate.renderError(schemeResults, error.message);
249
+ });
250
+ });
251
+
252
+ function displaySchemeResults(data) {
253
+ let html = `<div class="notification ${data.success ? 'is-success' : 'is-danger'}">
254
+ <strong>Scheme: ${escapeHtml(data.scheme_name)}</strong><br>
255
+ Overall Status: ${data.success ? 'PASSED' : 'FAILED'}
256
+ </div>`;
257
+
258
+ html += Legate.renderTestItems(data.tests);
259
+
260
+ schemeResults.innerHTML = html;
261
+ }
262
+
263
+ // Flow testing
264
+ const flowSchemeSelect = document.getElementById('flow-scheme-select');
265
+ const flowCredentialSelect = document.getElementById('flow-credential-select');
266
+ const flowTestBtn = document.getElementById('test-flow-btn');
267
+ const flowResults = document.getElementById('flow-test-results');
268
+
269
+ flowSchemeSelect.addEventListener('change', function() {
270
+ const schemeName = this.value;
271
+ flowCredentialSelect.disabled = !schemeName;
272
+ flowTestBtn.disabled = true;
273
+
274
+ if (schemeName) {
275
+ updateCompatibleCredentials(flowCredentialSelect, schemeName);
276
+ } else {
277
+ flowCredentialSelect.innerHTML = '<option value="">Select a credential...</option>';
278
+ }
279
+ });
280
+
281
+ flowCredentialSelect.addEventListener('change', function() {
282
+ flowTestBtn.disabled = !this.value || !flowSchemeSelect.value;
283
+ });
284
+
285
+ flowTestBtn.addEventListener('click', function() {
286
+ const schemeName = flowSchemeSelect.value;
287
+ const credentialName = flowCredentialSelect.value;
288
+
289
+ if (!schemeName || !credentialName) return;
290
+
291
+ this.classList.add('is-loading');
292
+ flowResults.innerHTML = '';
293
+
294
+ const formData = new FormData();
295
+ formData.append('scheme_name', schemeName);
296
+ formData.append('credential_name', credentialName);
297
+
298
+ Legate.apiRequest('/auth/test/flow', { method: 'POST', body: formData })
299
+ .then(data => {
300
+ this.classList.remove('is-loading');
301
+ displayFlowResults(data);
302
+ })
303
+ .catch(error => {
304
+ this.classList.remove('is-loading');
305
+ Legate.renderError(flowResults, error.message);
306
+ });
307
+ });
308
+
309
+ function displayFlowResults(data) {
310
+ let html = `<div class="notification ${data.success ? 'is-success' : 'is-danger'}">
311
+ <strong>Flow Type: ${escapeHtml(data.scheme_type)}</strong><br>
312
+ Overall Status: ${data.success ? 'SUCCESS' : 'FAILED'}
313
+ </div>`;
314
+
315
+ html += Legate.renderTestItems(data.steps, { labelKey: 'step', neutralClass: 'is-info' });
316
+
317
+ flowResults.innerHTML = html;
318
+ }
319
+
320
+ // API testing
321
+ const apiUrlInput = document.getElementById('api-test-url');
322
+ const apiSchemeSelect = document.getElementById('api-scheme-select');
323
+ const apiCredentialSelect = document.getElementById('api-credential-select');
324
+ const apiTestBtn = document.getElementById('test-api-btn');
325
+ const apiResults = document.getElementById('api-test-results');
326
+
327
+ apiSchemeSelect.addEventListener('change', function() {
328
+ const schemeName = this.value;
329
+ apiCredentialSelect.disabled = !schemeName;
330
+ updateTestApiButton();
331
+
332
+ if (schemeName) {
333
+ updateCompatibleCredentials(apiCredentialSelect, schemeName);
334
+ } else {
335
+ apiCredentialSelect.innerHTML = '<option value="">Select a credential...</option>';
336
+ }
337
+ });
338
+
339
+ apiCredentialSelect.addEventListener('change', updateTestApiButton);
340
+ apiUrlInput.addEventListener('input', updateTestApiButton);
341
+
342
+ function updateTestApiButton() {
343
+ apiTestBtn.disabled = !apiUrlInput.value || !apiSchemeSelect.value || !apiCredentialSelect.value;
344
+ }
345
+
346
+ apiTestBtn.addEventListener('click', function() {
347
+ const url = apiUrlInput.value;
348
+ const schemeName = apiSchemeSelect.value;
349
+ const credentialName = apiCredentialSelect.value;
350
+
351
+ if (!url || !schemeName || !credentialName) return;
352
+
353
+ this.classList.add('is-loading');
354
+ apiResults.innerHTML = '';
355
+
356
+ const formData = new FormData();
357
+ formData.append('url', url);
358
+ formData.append('scheme_name', schemeName);
359
+ formData.append('credential_name', credentialName);
360
+
361
+ Legate.apiRequest('/auth/test/api', { method: 'POST', body: formData })
362
+ .then(data => {
363
+ this.classList.remove('is-loading');
364
+ displayApiResults(data);
365
+ })
366
+ .catch(error => {
367
+ this.classList.remove('is-loading');
368
+ Legate.renderError(apiResults, error.message);
369
+ });
370
+ });
371
+
372
+ function displayApiResults(data) {
373
+ if (data.success) {
374
+ const statusClass = data.authenticated ? 'is-success' : 'is-warning';
375
+ let html = `<div class="notification ${statusClass}">
376
+ <strong>API Call Result</strong><br>
377
+ Status: ${escapeHtml(data.status_code)} ${escapeHtml(data.status_message)}<br>
378
+ Authenticated: ${data.authenticated ? 'YES' : 'NO'}
379
+ </div>`;
380
+
381
+ if (data.body_preview) {
382
+ html += `<div class="notification is-info is-small">
383
+ <strong>Response Preview:</strong><br>
384
+ <code>${escapeHtml(data.body_preview.substring(0, 200))}${data.body_preview.length > 200 ? '...' : ''}</code>
385
+ </div>`;
386
+ }
387
+
388
+ apiResults.innerHTML = html;
389
+ } else {
390
+ apiResults.innerHTML = `<div class="notification is-danger">
391
+ <strong>API Call Failed</strong><br>
392
+ Error: ${escapeHtml(data.error)}
393
+ </div>`;
394
+ }
395
+ }
396
+
397
+ // Helper function to update compatible credentials
398
+ function updateCompatibleCredentials(selectElement, schemeName) {
399
+ // This would ideally make an AJAX call to get compatible credentials
400
+ // For now, we'll populate with all credentials and let the server validate
401
+ selectElement.innerHTML = '<option value="">Select a credential...</option>';
402
+
403
+ // Get credentials from the original credential select dropdown
404
+ const credentialSelect = document.getElementById('credential-select');
405
+ const credentialOptions = credentialSelect.querySelectorAll('option');
406
+
407
+ credentialOptions.forEach(option => {
408
+ // Skip the placeholder option with empty value
409
+ if (option.value && option.value !== '') {
410
+ const newOption = document.createElement('option');
411
+ newOption.value = option.value;
412
+ newOption.textContent = option.textContent;
413
+ newOption.dataset.type = option.dataset.type;
414
+ selectElement.appendChild(newOption);
415
+ }
416
+ });
417
+ }
418
+ });