From 3d4590191eae7330c79296bd0ccd13a0477b06bf Mon Sep 17 00:00:00 2001 From: "kong[bot]" <123129154+kong[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 20:06:42 +0000 Subject: [PATCH] chore(api): sync OpenAPI contract --- .../generated/.openapi-generator/FILES | 48 + lib/volcano/generated/README.md | 98 +- .../generated/lib/volcano-generated.rb | 48 + .../volcano-generated/api/anon_keys_api.rb | 12 +- .../volcano-generated/api/auth_admin_api.rb | 18 +- .../api/auth_configuration_api.rb | 48 +- .../api/authentication_api.rb | 4 +- .../api/database_backups_api.rb | 18 +- .../api/database_branches_api.rb | 14 +- .../api/database_queries_api.rb | 4 +- .../volcano-generated/api/databases_api.rb | 28 +- .../api/durable_functions_api.rb | 79 +- .../volcano-generated/api/frontends_api.rb | 340 +- .../volcano-generated/api/functions_api.rb | 42 +- .../api/git_connections_api.rb | 26 +- .../lib/volcano-generated/api/logs_api.rb | 18 +- .../api/o_auth_configuration_api.rb | 12 +- .../api/project_access_tokens_api.rb | 479 + .../api/project_imports_api.rb | 8 + .../lib/volcano-generated/api/projects_api.rb | 122 +- .../lib/volcano-generated/api/realtime_api.rb | 6 +- .../volcano-generated/api/sandboxes_api.rb | 1433 ++ .../volcano-generated/api/service_keys_api.rb | 14 +- .../api/storage_admin_api.rb | 4 +- .../api/storage_buckets_api.rb | 10 +- .../api/storage_policies_api.rb | 6 +- .../lib/volcano-generated/api/system_api.rb | 308 + .../volcano-generated/api/variables_api.rb | 22 +- .../lib/volcano-generated/configuration.rb | 10 +- .../models/auth_insights_series_point.rb | 2 +- .../models/call_mcp200_response.rb | 220 + .../models/call_mcp200_response_error.rb | 190 + .../models/call_mcp200_response_id.rb | 105 + .../models/call_mcp_request.rb | 236 + .../models/call_mcp_request_id.rb | 105 + .../models/create_database_request.rb | 2 +- .../create_frontend_function_route_request.rb | 230 + .../create_project_access_token_request.rb | 241 + .../models/create_sandbox_session_request.rb | 305 + .../models/create_sandbox_template_request.rb | 248 + .../models/create_variable_request.rb | 1 + .../models/created_project_access_token.rb | 459 + .../models/database_query_performance_item.rb | 4 +- .../models/durable_execution_invocation.rb | 191 + .../models/durable_execution_operation.rb | 372 + .../durable_execution_operation_attempt.rb | 271 + .../durable_execution_operation_list.rb | 234 + .../lib/volcano-generated/models/frontend.rb | 46 +- .../models/frontend_custom_domain_response.rb | 12 +- .../models/frontend_deployment.rb | 88 +- .../models/frontend_function_route.rb | 375 + .../models/frontend_function_route_list.rb | 166 + .../lib/volcano-generated/models/function.rb | 13 +- .../models/function_deployment.rb | 70 +- .../models/function_runtime_option.rb | 29 +- .../models/log_activity_bucket.rb | 6 +- .../models/log_activity_request.rb | 6 +- .../models/log_search_response.rb | 4 +- .../models/metric_usage_data.rb | 2 +- .../models/paginated_project_access_tokens.rb | 279 + .../lib/volcano-generated/models/project.rb | 17 +- .../models/project_access_token.rb | 426 + .../models/project_access_token_scope.rb | 40 + .../models/project_access_token_usage.rb | 299 + .../project_access_token_usage_daily_entry.rb | 191 + .../models/project_config.rb | 24 +- .../models/project_config_database.rb | 2 +- .../models/project_config_frontend.rb | 105 +- .../project_config_frontend_function_route.rb | 240 + .../models/project_config_variable.rb | 1 + .../models/project_deployment.rb | 11 +- .../models/project_deployment_summary.rb | 2 +- .../models/project_frontend_custom_domain.rb | 12 +- .../models/publish_sandbox_preset_request.rb | 268 + ...place_frontend_shared_variables_request.rb | 237 + .../models/resolve_function_response.rb | 12 +- .../models/sandbox_access.rb | 216 + .../models/sandbox_access_request.rb | 221 + .../models/sandbox_capacity.rb | 199 + .../models/sandbox_capacity_list.rb | 166 + .../models/sandbox_command_request.rb | 251 + .../models/sandbox_command_result.rb | 294 + .../models/sandbox_deployment.rb | 242 + .../models/sandbox_deployment_page.rb | 192 + .../models/sandbox_execution_request.rb | 340 + .../models/sandbox_execution_result.rb | 381 + .../models/sandbox_file_read_request.rb | 182 + .../models/sandbox_file_result.rb | 164 + .../models/sandbox_file_write_request.rb | 217 + .../models/sandbox_pagination.rb | 199 + .../models/sandbox_preset.rb | 294 + .../models/sandbox_preset_list.rb | 166 + .../models/sandbox_session.rb | 407 + .../models/sandbox_session_page.rb | 192 + .../models/sandbox_subject_grant_request.rb | 164 + .../models/sandbox_template.rb | 321 + .../models/sandbox_template_page.rb | 192 + .../models/update_sandbox_template_request.rb | 175 + .../lib/volcano-generated/models/variable.rb | 12 +- openapi/openapi.yaml | 19221 +++++++++------- 100 files changed, 25623 insertions(+), 8463 deletions(-) create mode 100644 lib/volcano/generated/lib/volcano-generated/api/project_access_tokens_api.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/api/sandboxes_api.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_error.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_id.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/call_mcp_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/call_mcp_request_id.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/create_frontend_function_route_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/create_project_access_token_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/create_sandbox_session_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/create_sandbox_template_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/created_project_access_token.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/durable_execution_invocation.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_attempt.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_list.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/frontend_function_route.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/frontend_function_route_list.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/paginated_project_access_tokens.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/project_access_token.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/project_access_token_scope.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage_daily_entry.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/project_config_frontend_function_route.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/publish_sandbox_preset_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/replace_frontend_shared_variables_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_access.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_access_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity_list.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_command_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_command_result.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment_page.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_result.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_file_read_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_file_result.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_file_write_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_pagination.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_preset.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_preset_list.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_session.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_session_page.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_subject_grant_request.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_template.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/sandbox_template_page.rb create mode 100644 lib/volcano/generated/lib/volcano-generated/models/update_sandbox_template_request.rb diff --git a/lib/volcano/generated/.openapi-generator/FILES b/lib/volcano/generated/.openapi-generator/FILES index 1db736c8..7a3dec47 100644 --- a/lib/volcano/generated/.openapi-generator/FILES +++ b/lib/volcano/generated/.openapi-generator/FILES @@ -25,9 +25,11 @@ lib/volcano-generated/api/locks_api.rb lib/volcano-generated/api/logs_api.rb lib/volcano-generated/api/o_auth_authentication_api.rb lib/volcano-generated/api/o_auth_configuration_api.rb +lib/volcano-generated/api/project_access_tokens_api.rb lib/volcano-generated/api/project_imports_api.rb lib/volcano-generated/api/projects_api.rb lib/volcano-generated/api/realtime_api.rb +lib/volcano-generated/api/sandboxes_api.rb lib/volcano-generated/api/service_keys_api.rb lib/volcano-generated/api/storage_admin_api.rb lib/volcano-generated/api/storage_buckets_api.rb @@ -99,6 +101,11 @@ lib/volcano-generated/models/ban_auth_user_request.rb lib/volcano-generated/models/ban_user_response.rb lib/volcano-generated/models/batch_function_deploy_failure.rb lib/volcano-generated/models/batch_function_deploy_response.rb +lib/volcano-generated/models/call_mcp200_response.rb +lib/volcano-generated/models/call_mcp200_response_error.rb +lib/volcano-generated/models/call_mcp200_response_id.rb +lib/volcano-generated/models/call_mcp_request.rb +lib/volcano-generated/models/call_mcp_request_id.rb lib/volcano-generated/models/call_o_auth_provider_api200_response.rb lib/volcano-generated/models/call_o_auth_provider_api_request.rb lib/volcano-generated/models/complete_upload_session_response.rb @@ -112,15 +119,20 @@ lib/volcano-generated/models/create_database_request.rb lib/volcano-generated/models/create_database_restore_request.rb lib/volcano-generated/models/create_email_template_request.rb lib/volcano-generated/models/create_frontend_custom_domain_request.rb +lib/volcano-generated/models/create_frontend_function_route_request.rb lib/volcano-generated/models/create_function_scheduler_request.rb lib/volcano-generated/models/create_o_auth_config_request.rb +lib/volcano-generated/models/create_project_access_token_request.rb lib/volcano-generated/models/create_project_request.rb +lib/volcano-generated/models/create_sandbox_session_request.rb +lib/volcano-generated/models/create_sandbox_template_request.rb lib/volcano-generated/models/create_service_key_request.rb lib/volcano-generated/models/create_storage_bucket_request.rb lib/volcano-generated/models/create_storage_policy_request.rb lib/volcano-generated/models/create_upload_session_request.rb lib/volcano-generated/models/create_upload_session_response.rb lib/volcano-generated/models/create_variable_request.rb +lib/volcano-generated/models/created_project_access_token.rb lib/volcano-generated/models/database.rb lib/volcano-generated/models/database_backup.rb lib/volcano-generated/models/database_backup_list.rb @@ -154,6 +166,10 @@ lib/volcano-generated/models/deployment_reference.rb lib/volcano-generated/models/device_authorization_response.rb lib/volcano-generated/models/durable_execution.rb lib/volcano-generated/models/durable_execution_error.rb +lib/volcano-generated/models/durable_execution_invocation.rb +lib/volcano-generated/models/durable_execution_operation.rb +lib/volcano-generated/models/durable_execution_operation_attempt.rb +lib/volcano-generated/models/durable_execution_operation_list.rb lib/volcano-generated/models/durable_execution_status.rb lib/volcano-generated/models/durable_function.rb lib/volcano-generated/models/durable_function_config.rb @@ -166,6 +182,8 @@ lib/volcano-generated/models/frontend_custom_domain_tls_config.rb lib/volcano-generated/models/frontend_deployment.rb lib/volcano-generated/models/frontend_domain_routing_record.rb lib/volcano-generated/models/frontend_domain_verification_record.rb +lib/volcano-generated/models/frontend_function_route.rb +lib/volcano-generated/models/frontend_function_route_list.rb lib/volcano-generated/models/frontend_usage_daily_entry.rb lib/volcano-generated/models/frontend_usage_data.rb lib/volcano-generated/models/frontend_usage_history_response.rb @@ -240,6 +258,7 @@ lib/volcano-generated/models/paginated_frontend_deployments.rb lib/volcano-generated/models/paginated_frontends.rb lib/volcano-generated/models/paginated_function_deployments.rb lib/volcano-generated/models/paginated_functions.rb +lib/volcano-generated/models/paginated_project_access_tokens.rb lib/volcano-generated/models/paginated_project_custom_domains.rb lib/volcano-generated/models/paginated_project_deployments.rb lib/volcano-generated/models/paginated_projects.rb @@ -250,6 +269,10 @@ lib/volcano-generated/models/platform_exchange_response.rb lib/volcano-generated/models/preview_auth_page_request.rb lib/volcano-generated/models/preview_auth_page_response.rb lib/volcano-generated/models/project.rb +lib/volcano-generated/models/project_access_token.rb +lib/volcano-generated/models/project_access_token_scope.rb +lib/volcano-generated/models/project_access_token_usage.rb +lib/volcano-generated/models/project_access_token_usage_daily_entry.rb lib/volcano-generated/models/project_config.rb lib/volcano-generated/models/project_config_apply_result.rb lib/volcano-generated/models/project_config_apply_result_entry.rb @@ -279,6 +302,7 @@ lib/volcano-generated/models/project_config_database.rb lib/volcano-generated/models/project_config_email_template.rb lib/volcano-generated/models/project_config_email_templates.rb lib/volcano-generated/models/project_config_frontend.rb +lib/volcano-generated/models/project_config_frontend_function_route.rb lib/volcano-generated/models/project_config_function.rb lib/volcano-generated/models/project_config_hosted_page.rb lib/volcano-generated/models/project_config_hosted_pages.rb @@ -345,14 +369,37 @@ lib/volcano-generated/models/project_source_export_omission.rb lib/volcano-generated/models/project_source_export_skip.rb lib/volcano-generated/models/project_source_export_state.rb lib/volcano-generated/models/project_usage_response.rb +lib/volcano-generated/models/publish_sandbox_preset_request.rb lib/volcano-generated/models/realtime_config.rb lib/volcano-generated/models/realtime_plan_limits.rb lib/volcano-generated/models/realtime_stats.rb lib/volcano-generated/models/refresh_o_auth_provider_token200_response.rb +lib/volcano-generated/models/replace_frontend_shared_variables_request.rb lib/volcano-generated/models/replace_shared_variables_request.rb lib/volcano-generated/models/reset_database_password200_response.rb lib/volcano-generated/models/resolve_function_response.rb lib/volcano-generated/models/resource_reference.rb +lib/volcano-generated/models/sandbox_access.rb +lib/volcano-generated/models/sandbox_access_request.rb +lib/volcano-generated/models/sandbox_capacity.rb +lib/volcano-generated/models/sandbox_capacity_list.rb +lib/volcano-generated/models/sandbox_command_request.rb +lib/volcano-generated/models/sandbox_command_result.rb +lib/volcano-generated/models/sandbox_deployment.rb +lib/volcano-generated/models/sandbox_deployment_page.rb +lib/volcano-generated/models/sandbox_execution_request.rb +lib/volcano-generated/models/sandbox_execution_result.rb +lib/volcano-generated/models/sandbox_file_read_request.rb +lib/volcano-generated/models/sandbox_file_result.rb +lib/volcano-generated/models/sandbox_file_write_request.rb +lib/volcano-generated/models/sandbox_pagination.rb +lib/volcano-generated/models/sandbox_preset.rb +lib/volcano-generated/models/sandbox_preset_list.rb +lib/volcano-generated/models/sandbox_session.rb +lib/volcano-generated/models/sandbox_session_page.rb +lib/volcano-generated/models/sandbox_subject_grant_request.rb +lib/volcano-generated/models/sandbox_template.rb +lib/volcano-generated/models/sandbox_template_page.rb lib/volcano-generated/models/schedule_request.rb lib/volcano-generated/models/service_key.rb lib/volcano-generated/models/set_project_git_production_branch_request.rb @@ -381,6 +428,7 @@ lib/volcano-generated/models/update_o_auth_config_request.rb lib/volcano-generated/models/update_project_git_deploy_settings_request.rb lib/volcano-generated/models/update_project_request.rb lib/volcano-generated/models/update_realtime_config_request.rb +lib/volcano-generated/models/update_sandbox_template_request.rb lib/volcano-generated/models/update_storage_bucket_request.rb lib/volcano-generated/models/update_variable_request.rb lib/volcano-generated/models/upload_session_part.rb diff --git a/lib/volcano/generated/README.md b/lib/volcano/generated/README.md index 33abb17d..6ff14fcf 100644 --- a/lib/volcano/generated/README.md +++ b/lib/volcano/generated/README.md @@ -61,7 +61,12 @@ require 'volcano-generated' # Setup authorization Volcano::Generated.configure do |config| - # Configure Bearer authorization (JWT): UserToken + # Configure Bearer authorization (opaque): UserToken + config.access_token = 'YOUR_BEARER_TOKEN' + # Configure a proc to get access tokens in lieu of the static access_token configuration + config.access_token_getter = -> { 'YOUR TOKEN GETTER PROC' } + + # Configure Bearer authorization (opaque): ProjectAccessToken config.access_token = 'YOUR_BEARER_TOKEN' # Configure a proc to get access tokens in lieu of the static access_token configuration config.access_token_getter = -> { 'YOUR TOKEN GETTER PROC' } @@ -176,7 +181,7 @@ Class | Method | HTTP request | Description *Volcano::Generated::DatabaseQueriesApi* | [**query_database_ping**](docs/DatabaseQueriesApi.md#query_database_ping) | **POST** /databases/{databaseName}/query/ping | Database connectivity probe (REST API) *Volcano::Generated::DatabaseQueriesApi* | [**query_database_select**](docs/DatabaseQueriesApi.md#query_database_select) | **POST** /databases/{databaseName}/query/select | Query database with SELECT (REST API) *Volcano::Generated::DatabaseQueriesApi* | [**query_database_update**](docs/DatabaseQueriesApi.md#query_database_update) | **POST** /databases/{databaseName}/query/update | Update data in database (REST API) -*Volcano::Generated::DatabasesApi* | [**create_database**](docs/DatabasesApi.md#create_database) | **POST** /projects/{id}/databases | Create a new serverless PostgreSQL database +*Volcano::Generated::DatabasesApi* | [**create_database**](docs/DatabasesApi.md#create_database) | **POST** /projects/{id}/databases | Create a new PostgreSQL database *Volcano::Generated::DatabasesApi* | [**delete_database**](docs/DatabasesApi.md#delete_database) | **DELETE** /projects/{id}/databases/{databaseName} | Delete a database *Volcano::Generated::DatabasesApi* | [**get_database**](docs/DatabasesApi.md#get_database) | **GET** /projects/{id}/databases/{databaseName} | Get database details *Volcano::Generated::DatabasesApi* | [**get_database_stats**](docs/DatabasesApi.md#get_database_stats) | **GET** /projects/{id}/databases/{databaseName}/stats | Get database consumption metrics @@ -193,6 +198,7 @@ Class | Method | HTTP request | Description *Volcano::Generated::DurableFunctionsApi* | [**get_durable_execution**](docs/DurableFunctionsApi.md#get_durable_execution) | **GET** /projects/{id}/durable-functions/{functionId}/executions/{executionId} | Get a durable execution *Volcano::Generated::DurableFunctionsApi* | [**get_durable_function**](docs/DurableFunctionsApi.md#get_durable_function) | **GET** /projects/{id}/durable-functions/{functionId} | Get durable function by ID or name *Volcano::Generated::DurableFunctionsApi* | [**get_durable_function_scheduler**](docs/DurableFunctionsApi.md#get_durable_function_scheduler) | **GET** /projects/{id}/durable-functions/{functionId}/schedulers/{schedulerId} | Get a durable function scheduler +*Volcano::Generated::DurableFunctionsApi* | [**list_durable_execution_operations**](docs/DurableFunctionsApi.md#list_durable_execution_operations) | **GET** /projects/{id}/durable-functions/{functionId}/executions/{executionId}/operations | List a durable execution's operations *Volcano::Generated::DurableFunctionsApi* | [**list_durable_executions**](docs/DurableFunctionsApi.md#list_durable_executions) | **GET** /projects/{id}/durable-functions/{functionId}/executions | List a durable function's executions *Volcano::Generated::DurableFunctionsApi* | [**list_durable_function_deployments**](docs/DurableFunctionsApi.md#list_durable_function_deployments) | **GET** /projects/{id}/durable-functions/{functionId}/deployments | List durable function deployments *Volcano::Generated::DurableFunctionsApi* | [**list_durable_function_schedulers**](docs/DurableFunctionsApi.md#list_durable_function_schedulers) | **GET** /projects/{id}/durable-functions/{functionId}/schedulers | List schedulers for a durable function @@ -203,15 +209,19 @@ Class | Method | HTTP request | Description *Volcano::Generated::DurableFunctionsApi* | [**update_durable_function_scheduler**](docs/DurableFunctionsApi.md#update_durable_function_scheduler) | **PATCH** /projects/{id}/durable-functions/{functionId}/schedulers/{schedulerId} | Update a durable function scheduler *Volcano::Generated::FrontendsApi* | [**create_frontend**](docs/FrontendsApi.md#create_frontend) | **POST** /projects/{id}/frontends | Create a new frontend deployment *Volcano::Generated::FrontendsApi* | [**create_frontend_custom_domain**](docs/FrontendsApi.md#create_frontend_custom_domain) | **POST** /projects/{id}/frontends/{frontendId}/domain | Configure frontend custom domain (SUPERAGENT) +*Volcano::Generated::FrontendsApi* | [**create_frontend_function_route**](docs/FrontendsApi.md#create_frontend_function_route) | **POST** /projects/{id}/frontends/{frontendId}/function-routes | Route a Frontend path to an HTTP Function *Volcano::Generated::FrontendsApi* | [**delete_frontend**](docs/FrontendsApi.md#delete_frontend) | **DELETE** /projects/{id}/frontends/{frontendId} | Delete a frontend *Volcano::Generated::FrontendsApi* | [**delete_frontend_custom_domain**](docs/FrontendsApi.md#delete_frontend_custom_domain) | **DELETE** /projects/{id}/frontends/{frontendId}/domain | Delete frontend custom domain +*Volcano::Generated::FrontendsApi* | [**delete_frontend_function_route**](docs/FrontendsApi.md#delete_frontend_function_route) | **DELETE** /projects/{id}/frontends/{frontendId}/function-routes/{routeId} | Delete a Frontend Function route *Volcano::Generated::FrontendsApi* | [**get_frontend**](docs/FrontendsApi.md#get_frontend) | **GET** /projects/{id}/frontends/{frontendId} | Get frontend details *Volcano::Generated::FrontendsApi* | [**get_frontend_custom_domain**](docs/FrontendsApi.md#get_frontend_custom_domain) | **GET** /projects/{id}/frontends/{frontendId}/domain | Get frontend custom domain status *Volcano::Generated::FrontendsApi* | [**get_frontend_usage_history**](docs/FrontendsApi.md#get_frontend_usage_history) | **GET** /projects/{id}/frontends/{frontendId}/usage | Per-day request and error counts for a single frontend *Volcano::Generated::FrontendsApi* | [**list_frontend_deployments**](docs/FrontendsApi.md#list_frontend_deployments) | **GET** /projects/{id}/frontends/{frontendId}/deployments | List frontend deployments +*Volcano::Generated::FrontendsApi* | [**list_frontend_function_routes**](docs/FrontendsApi.md#list_frontend_function_routes) | **GET** /projects/{id}/frontends/{frontendId}/function-routes | List a Frontend's Function routes *Volcano::Generated::FrontendsApi* | [**list_frontends**](docs/FrontendsApi.md#list_frontends) | **GET** /projects/{id}/frontends | List all frontends in a project *Volcano::Generated::FrontendsApi* | [**list_project_custom_domains**](docs/FrontendsApi.md#list_project_custom_domains) | **GET** /projects/{id}/domains | List all custom domains in a project *Volcano::Generated::FrontendsApi* | [**redeploy_frontend**](docs/FrontendsApi.md#redeploy_frontend) | **POST** /projects/{id}/frontends/{frontendId}/redeploy | Redeploy frontend using latest uploaded artifact +*Volcano::Generated::FrontendsApi* | [**update_frontend_function_route**](docs/FrontendsApi.md#update_frontend_function_route) | **PUT** /projects/{id}/frontends/{frontendId}/function-routes/{routeId} | Replace a Frontend Function route *Volcano::Generated::FunctionsApi* | [**create_function**](docs/FunctionsApi.md#create_function) | **POST** /projects/{id}/functions | Create or update function code *Volcano::Generated::FunctionsApi* | [**create_function_scheduler**](docs/FunctionsApi.md#create_function_scheduler) | **POST** /projects/{id}/functions/{functionId}/schedulers | Create a scheduler for a function *Volcano::Generated::FunctionsApi* | [**create_functions_batch**](docs/FunctionsApi.md#create_functions_batch) | **POST** /projects/{id}/functions/batch | Deploy multiple functions in one request @@ -271,6 +281,12 @@ Class | Method | HTTP request | Description *Volcano::Generated::OAuthConfigurationApi* | [**list_available_o_auth_providers**](docs/OAuthConfigurationApi.md#list_available_o_auth_providers) | **GET** /projects/{id}/oauth/providers | List available OAuth providers *Volcano::Generated::OAuthConfigurationApi* | [**list_o_auth_configs**](docs/OAuthConfigurationApi.md#list_o_auth_configs) | **GET** /projects/{id}/oauth/configs | List OAuth configurations *Volcano::Generated::OAuthConfigurationApi* | [**update_o_auth_config**](docs/OAuthConfigurationApi.md#update_o_auth_config) | **PUT** /projects/{id}/oauth/configs/{provider} | Update OAuth configuration +*Volcano::Generated::ProjectAccessTokensApi* | [**create_project_access_token**](docs/ProjectAccessTokensApi.md#create_project_access_token) | **POST** /projects/{id}/access-tokens | Create a project access token +*Volcano::Generated::ProjectAccessTokensApi* | [**get_project_access_token**](docs/ProjectAccessTokensApi.md#get_project_access_token) | **GET** /projects/{id}/access-tokens/{tokenId} | Get a project access token +*Volcano::Generated::ProjectAccessTokensApi* | [**get_project_access_token_usage**](docs/ProjectAccessTokensApi.md#get_project_access_token_usage) | **GET** /projects/{id}/access-tokens/{tokenId}/usage | Per-day request counts for one access token +*Volcano::Generated::ProjectAccessTokensApi* | [**list_project_access_tokens**](docs/ProjectAccessTokensApi.md#list_project_access_tokens) | **GET** /projects/{id}/access-tokens | List a project's access tokens +*Volcano::Generated::ProjectAccessTokensApi* | [**list_project_access_tokens_usage**](docs/ProjectAccessTokensApi.md#list_project_access_tokens_usage) | **GET** /projects/{id}/access-tokens/usage | Per-day request counts for every access token in a project +*Volcano::Generated::ProjectAccessTokensApi* | [**revoke_project_access_token**](docs/ProjectAccessTokensApi.md#revoke_project_access_token) | **DELETE** /projects/{id}/access-tokens/{tokenId} | Revoke a project access token *Volcano::Generated::ProjectImportsApi* | [**complete_import_connect**](docs/ProjectImportsApi.md#complete_import_connect) | **GET** /imports/{provider}/callback | Complete a project import provider connection *Volcano::Generated::ProjectImportsApi* | [**delete_import_connection**](docs/ProjectImportsApi.md#delete_import_connection) | **DELETE** /user/imports/connections/{connectionId} | Delete a project import provider connection *Volcano::Generated::ProjectImportsApi* | [**get_project_import_run**](docs/ProjectImportsApi.md#get_project_import_run) | **GET** /imports/{provider}/runs/{runId} | Get a project import run @@ -299,6 +315,7 @@ Class | Method | HTTP request | Description *Volcano::Generated::ProjectsApi* | [**list_project_deployments**](docs/ProjectsApi.md#list_project_deployments) | **GET** /projects/{id}/deployments | List deployments in a project *Volcano::Generated::ProjectsApi* | [**list_projects**](docs/ProjectsApi.md#list_projects) | **GET** /projects | List all projects for authenticated user *Volcano::Generated::ProjectsApi* | [**query_project_metrics**](docs/ProjectsApi.md#query_project_metrics) | **POST** /projects/{id}/metrics/query | Query project runtime metrics +*Volcano::Generated::ProjectsApi* | [**replace_frontend_shared_variables**](docs/ProjectsApi.md#replace_frontend_shared_variables) | **PUT** /projects/{id}/frontend-shared-variables | Replace frontend shared variable names *Volcano::Generated::ProjectsApi* | [**replace_shared_variables**](docs/ProjectsApi.md#replace_shared_variables) | **PUT** /projects/{id}/shared-variables | Replace shared variable names *Volcano::Generated::ProjectsApi* | [**set_project_git_production_branch**](docs/ProjectsApi.md#set_project_git_production_branch) | **PUT** /projects/{id}/git-connection/production-branch | Set the branch a project deploys from *Volcano::Generated::ProjectsApi* | [**summarize_project_deployments**](docs/ProjectsApi.md#summarize_project_deployments) | **GET** /projects/{id}/deployments/summary | Summarize deployments in a project @@ -308,6 +325,26 @@ Class | Method | HTTP request | Description *Volcano::Generated::RealtimeApi* | [**get_realtime_config**](docs/RealtimeApi.md#get_realtime_config) | **GET** /projects/{id}/realtime/config | Get realtime configuration for a project *Volcano::Generated::RealtimeApi* | [**get_realtime_stats**](docs/RealtimeApi.md#get_realtime_stats) | **GET** /projects/{id}/realtime/stats | Get realtime statistics for a project *Volcano::Generated::RealtimeApi* | [**update_realtime_config**](docs/RealtimeApi.md#update_realtime_config) | **PUT** /projects/{id}/realtime/config | Update realtime configuration for a project +*Volcano::Generated::SandboxesApi* | [**create_sandbox**](docs/SandboxesApi.md#create_sandbox) | **POST** /projects/{id}/sandboxes | Create a sandbox template from a verified preset +*Volcano::Generated::SandboxesApi* | [**create_sandbox_session**](docs/SandboxesApi.md#create_sandbox_session) | **POST** /projects/{id}/sandbox-sessions | Start a sandbox session +*Volcano::Generated::SandboxesApi* | [**create_sandbox_session_access**](docs/SandboxesApi.md#create_sandbox_session_access) | **POST** /sandbox-sessions/{sessionId}/access | Issue a short-lived port-scoped access credential +*Volcano::Generated::SandboxesApi* | [**delete_sandbox**](docs/SandboxesApi.md#delete_sandbox) | **DELETE** /projects/{id}/sandboxes/{sandboxId} | Retire a template and terminate its sessions +*Volcano::Generated::SandboxesApi* | [**execute_sandbox**](docs/SandboxesApi.md#execute_sandbox) | **POST** /projects/{id}/sandbox-executions | Execute once and return after confirmed termination +*Volcano::Generated::SandboxesApi* | [**execute_sandbox_session**](docs/SandboxesApi.md#execute_sandbox_session) | **POST** /sandbox-sessions/{sessionId}/exec | Execute a command within a session +*Volcano::Generated::SandboxesApi* | [**get_sandbox**](docs/SandboxesApi.md#get_sandbox) | **GET** /projects/{id}/sandboxes/{sandboxId} | Get a sandbox template +*Volcano::Generated::SandboxesApi* | [**get_sandbox_session**](docs/SandboxesApi.md#get_sandbox_session) | **GET** /sandbox-sessions/{sessionId} | Get a sandbox session +*Volcano::Generated::SandboxesApi* | [**grant_sandbox_session**](docs/SandboxesApi.md#grant_sandbox_session) | **PUT** /sandbox-sessions/{sessionId}/grants/{subjectId} | Authorize an authenticated project user for this session +*Volcano::Generated::SandboxesApi* | [**list_sandbox_deployments**](docs/SandboxesApi.md#list_sandbox_deployments) | **GET** /projects/{id}/sandboxes/{sandboxId}/deployments | List sandbox deployment history +*Volcano::Generated::SandboxesApi* | [**list_sandbox_presets**](docs/SandboxesApi.md#list_sandbox_presets) | **GET** /sandboxes/presets | List available sandbox presets +*Volcano::Generated::SandboxesApi* | [**list_sandbox_sessions**](docs/SandboxesApi.md#list_sandbox_sessions) | **GET** /projects/{id}/sandbox-sessions | List project sandbox sessions +*Volcano::Generated::SandboxesApi* | [**list_sandboxes**](docs/SandboxesApi.md#list_sandboxes) | **GET** /projects/{id}/sandboxes | List sandbox templates +*Volcano::Generated::SandboxesApi* | [**read_sandbox_session_file**](docs/SandboxesApi.md#read_sandbox_session_file) | **POST** /sandbox-sessions/{sessionId}/files/read | Read a workspace file +*Volcano::Generated::SandboxesApi* | [**resume_sandbox_session**](docs/SandboxesApi.md#resume_sandbox_session) | **POST** /sandbox-sessions/{sessionId}/resume | Resume a sandbox session +*Volcano::Generated::SandboxesApi* | [**revoke_sandbox_session**](docs/SandboxesApi.md#revoke_sandbox_session) | **DELETE** /sandbox-sessions/{sessionId}/grants/{subjectId} | Revoke a project user session grant +*Volcano::Generated::SandboxesApi* | [**suspend_sandbox_session**](docs/SandboxesApi.md#suspend_sandbox_session) | **POST** /sandbox-sessions/{sessionId}/suspend | Suspend a sandbox session +*Volcano::Generated::SandboxesApi* | [**terminate_sandbox_session**](docs/SandboxesApi.md#terminate_sandbox_session) | **DELETE** /sandbox-sessions/{sessionId} | Request sandbox termination +*Volcano::Generated::SandboxesApi* | [**update_sandbox**](docs/SandboxesApi.md#update_sandbox) | **PATCH** /projects/{id}/sandboxes/{sandboxId} | Rename a sandbox template +*Volcano::Generated::SandboxesApi* | [**write_sandbox_session_file**](docs/SandboxesApi.md#write_sandbox_session_file) | **POST** /sandbox-sessions/{sessionId}/files/write | Write a workspace file *Volcano::Generated::ServiceKeysApi* | [**create_service_key**](docs/ServiceKeysApi.md#create_service_key) | **POST** /projects/{id}/service-keys | Create service key *Volcano::Generated::ServiceKeysApi* | [**delete_service_key**](docs/ServiceKeysApi.md#delete_service_key) | **DELETE** /projects/{id}/service-keys/{keyId} | Delete service key *Volcano::Generated::ServiceKeysApi* | [**get_service_key**](docs/ServiceKeysApi.md#get_service_key) | **GET** /projects/{id}/service-keys/{keyId} | Get service key @@ -332,6 +369,11 @@ Class | Method | HTTP request | Description *Volcano::Generated::StoragePoliciesApi* | [**create_storage_policy**](docs/StoragePoliciesApi.md#create_storage_policy) | **POST** /projects/{id}/storage/buckets/{bucketName}/policies | Create a storage policy *Volcano::Generated::StoragePoliciesApi* | [**delete_storage_policy**](docs/StoragePoliciesApi.md#delete_storage_policy) | **DELETE** /projects/{id}/storage/buckets/{bucketName}/policies/{policyId} | Delete a storage policy *Volcano::Generated::StoragePoliciesApi* | [**list_storage_policies**](docs/StoragePoliciesApi.md#list_storage_policies) | **GET** /projects/{id}/storage/buckets/{bucketName}/policies | List storage policies for a bucket +*Volcano::Generated::SystemApi* | [**call_mcp**](docs/SystemApi.md#call_mcp) | **POST** /mcp | Model Context Protocol endpoint +*Volcano::Generated::SystemApi* | [**get_open_api_spec_json**](docs/SystemApi.md#get_open_api_spec_json) | **GET** /openapi.json | Fetch the OpenAPI specification as JSON +*Volcano::Generated::SystemApi* | [**get_open_api_spec_yaml**](docs/SystemApi.md#get_open_api_spec_yaml) | **GET** /openapi.yaml | Fetch the OpenAPI specification as YAML +*Volcano::Generated::SystemApi* | [**head_open_api_spec_json**](docs/SystemApi.md#head_open_api_spec_json) | **HEAD** /openapi.json | Check the JSON OpenAPI specification +*Volcano::Generated::SystemApi* | [**head_open_api_spec_yaml**](docs/SystemApi.md#head_open_api_spec_yaml) | **HEAD** /openapi.yaml | Check the YAML OpenAPI specification *Volcano::Generated::SystemApi* | [**health_check**](docs/SystemApi.md#health_check) | **GET** /health | Health check endpoint *Volcano::Generated::VariablesApi* | [**create_variable**](docs/VariablesApi.md#create_variable) | **POST** /projects/{id}/variables | Create or update a variable *Volcano::Generated::VariablesApi* | [**delete_variable**](docs/VariablesApi.md#delete_variable) | **DELETE** /projects/{id}/variables/{name} | Delete a variable @@ -402,6 +444,11 @@ Class | Method | HTTP request | Description - [Volcano::Generated::BanUserResponse](docs/BanUserResponse.md) - [Volcano::Generated::BatchFunctionDeployFailure](docs/BatchFunctionDeployFailure.md) - [Volcano::Generated::BatchFunctionDeployResponse](docs/BatchFunctionDeployResponse.md) + - [Volcano::Generated::CallMCP200Response](docs/CallMCP200Response.md) + - [Volcano::Generated::CallMCP200ResponseError](docs/CallMCP200ResponseError.md) + - [Volcano::Generated::CallMCP200ResponseId](docs/CallMCP200ResponseId.md) + - [Volcano::Generated::CallMCPRequest](docs/CallMCPRequest.md) + - [Volcano::Generated::CallMCPRequestId](docs/CallMCPRequestId.md) - [Volcano::Generated::CallOAuthProviderAPI200Response](docs/CallOAuthProviderAPI200Response.md) - [Volcano::Generated::CallOAuthProviderAPIRequest](docs/CallOAuthProviderAPIRequest.md) - [Volcano::Generated::CompleteUploadSessionResponse](docs/CompleteUploadSessionResponse.md) @@ -415,15 +462,20 @@ Class | Method | HTTP request | Description - [Volcano::Generated::CreateDatabaseRestoreRequest](docs/CreateDatabaseRestoreRequest.md) - [Volcano::Generated::CreateEmailTemplateRequest](docs/CreateEmailTemplateRequest.md) - [Volcano::Generated::CreateFrontendCustomDomainRequest](docs/CreateFrontendCustomDomainRequest.md) + - [Volcano::Generated::CreateFrontendFunctionRouteRequest](docs/CreateFrontendFunctionRouteRequest.md) - [Volcano::Generated::CreateFunctionSchedulerRequest](docs/CreateFunctionSchedulerRequest.md) - [Volcano::Generated::CreateOAuthConfigRequest](docs/CreateOAuthConfigRequest.md) + - [Volcano::Generated::CreateProjectAccessTokenRequest](docs/CreateProjectAccessTokenRequest.md) - [Volcano::Generated::CreateProjectRequest](docs/CreateProjectRequest.md) + - [Volcano::Generated::CreateSandboxSessionRequest](docs/CreateSandboxSessionRequest.md) + - [Volcano::Generated::CreateSandboxTemplateRequest](docs/CreateSandboxTemplateRequest.md) - [Volcano::Generated::CreateServiceKeyRequest](docs/CreateServiceKeyRequest.md) - [Volcano::Generated::CreateStorageBucketRequest](docs/CreateStorageBucketRequest.md) - [Volcano::Generated::CreateStoragePolicyRequest](docs/CreateStoragePolicyRequest.md) - [Volcano::Generated::CreateUploadSessionRequest](docs/CreateUploadSessionRequest.md) - [Volcano::Generated::CreateUploadSessionResponse](docs/CreateUploadSessionResponse.md) - [Volcano::Generated::CreateVariableRequest](docs/CreateVariableRequest.md) + - [Volcano::Generated::CreatedProjectAccessToken](docs/CreatedProjectAccessToken.md) - [Volcano::Generated::Database](docs/Database.md) - [Volcano::Generated::DatabaseBackup](docs/DatabaseBackup.md) - [Volcano::Generated::DatabaseBackupList](docs/DatabaseBackupList.md) @@ -457,6 +509,10 @@ Class | Method | HTTP request | Description - [Volcano::Generated::DeviceAuthorizationResponse](docs/DeviceAuthorizationResponse.md) - [Volcano::Generated::DurableExecution](docs/DurableExecution.md) - [Volcano::Generated::DurableExecutionError](docs/DurableExecutionError.md) + - [Volcano::Generated::DurableExecutionInvocation](docs/DurableExecutionInvocation.md) + - [Volcano::Generated::DurableExecutionOperation](docs/DurableExecutionOperation.md) + - [Volcano::Generated::DurableExecutionOperationAttempt](docs/DurableExecutionOperationAttempt.md) + - [Volcano::Generated::DurableExecutionOperationList](docs/DurableExecutionOperationList.md) - [Volcano::Generated::DurableExecutionStatus](docs/DurableExecutionStatus.md) - [Volcano::Generated::DurableFunction](docs/DurableFunction.md) - [Volcano::Generated::DurableFunctionConfig](docs/DurableFunctionConfig.md) @@ -469,6 +525,8 @@ Class | Method | HTTP request | Description - [Volcano::Generated::FrontendDeployment](docs/FrontendDeployment.md) - [Volcano::Generated::FrontendDomainRoutingRecord](docs/FrontendDomainRoutingRecord.md) - [Volcano::Generated::FrontendDomainVerificationRecord](docs/FrontendDomainVerificationRecord.md) + - [Volcano::Generated::FrontendFunctionRoute](docs/FrontendFunctionRoute.md) + - [Volcano::Generated::FrontendFunctionRouteList](docs/FrontendFunctionRouteList.md) - [Volcano::Generated::FrontendUsageDailyEntry](docs/FrontendUsageDailyEntry.md) - [Volcano::Generated::FrontendUsageData](docs/FrontendUsageData.md) - [Volcano::Generated::FrontendUsageHistoryResponse](docs/FrontendUsageHistoryResponse.md) @@ -543,6 +601,7 @@ Class | Method | HTTP request | Description - [Volcano::Generated::PaginatedFrontends](docs/PaginatedFrontends.md) - [Volcano::Generated::PaginatedFunctionDeployments](docs/PaginatedFunctionDeployments.md) - [Volcano::Generated::PaginatedFunctions](docs/PaginatedFunctions.md) + - [Volcano::Generated::PaginatedProjectAccessTokens](docs/PaginatedProjectAccessTokens.md) - [Volcano::Generated::PaginatedProjectCustomDomains](docs/PaginatedProjectCustomDomains.md) - [Volcano::Generated::PaginatedProjectDeployments](docs/PaginatedProjectDeployments.md) - [Volcano::Generated::PaginatedProjects](docs/PaginatedProjects.md) @@ -553,6 +612,10 @@ Class | Method | HTTP request | Description - [Volcano::Generated::PreviewAuthPageRequest](docs/PreviewAuthPageRequest.md) - [Volcano::Generated::PreviewAuthPageResponse](docs/PreviewAuthPageResponse.md) - [Volcano::Generated::Project](docs/Project.md) + - [Volcano::Generated::ProjectAccessToken](docs/ProjectAccessToken.md) + - [Volcano::Generated::ProjectAccessTokenScope](docs/ProjectAccessTokenScope.md) + - [Volcano::Generated::ProjectAccessTokenUsage](docs/ProjectAccessTokenUsage.md) + - [Volcano::Generated::ProjectAccessTokenUsageDailyEntry](docs/ProjectAccessTokenUsageDailyEntry.md) - [Volcano::Generated::ProjectConfig](docs/ProjectConfig.md) - [Volcano::Generated::ProjectConfigApplyResult](docs/ProjectConfigApplyResult.md) - [Volcano::Generated::ProjectConfigApplyResultEntry](docs/ProjectConfigApplyResultEntry.md) @@ -582,6 +645,7 @@ Class | Method | HTTP request | Description - [Volcano::Generated::ProjectConfigEmailTemplate](docs/ProjectConfigEmailTemplate.md) - [Volcano::Generated::ProjectConfigEmailTemplates](docs/ProjectConfigEmailTemplates.md) - [Volcano::Generated::ProjectConfigFrontend](docs/ProjectConfigFrontend.md) + - [Volcano::Generated::ProjectConfigFrontendFunctionRoute](docs/ProjectConfigFrontendFunctionRoute.md) - [Volcano::Generated::ProjectConfigFunction](docs/ProjectConfigFunction.md) - [Volcano::Generated::ProjectConfigHostedPage](docs/ProjectConfigHostedPage.md) - [Volcano::Generated::ProjectConfigHostedPages](docs/ProjectConfigHostedPages.md) @@ -648,14 +712,37 @@ Class | Method | HTTP request | Description - [Volcano::Generated::ProjectSourceExportSkip](docs/ProjectSourceExportSkip.md) - [Volcano::Generated::ProjectSourceExportState](docs/ProjectSourceExportState.md) - [Volcano::Generated::ProjectUsageResponse](docs/ProjectUsageResponse.md) + - [Volcano::Generated::PublishSandboxPresetRequest](docs/PublishSandboxPresetRequest.md) - [Volcano::Generated::RealtimeConfig](docs/RealtimeConfig.md) - [Volcano::Generated::RealtimePlanLimits](docs/RealtimePlanLimits.md) - [Volcano::Generated::RealtimeStats](docs/RealtimeStats.md) - [Volcano::Generated::RefreshOAuthProviderToken200Response](docs/RefreshOAuthProviderToken200Response.md) + - [Volcano::Generated::ReplaceFrontendSharedVariablesRequest](docs/ReplaceFrontendSharedVariablesRequest.md) - [Volcano::Generated::ReplaceSharedVariablesRequest](docs/ReplaceSharedVariablesRequest.md) - [Volcano::Generated::ResetDatabasePassword200Response](docs/ResetDatabasePassword200Response.md) - [Volcano::Generated::ResolveFunctionResponse](docs/ResolveFunctionResponse.md) - [Volcano::Generated::ResourceReference](docs/ResourceReference.md) + - [Volcano::Generated::SandboxAccess](docs/SandboxAccess.md) + - [Volcano::Generated::SandboxAccessRequest](docs/SandboxAccessRequest.md) + - [Volcano::Generated::SandboxCapacity](docs/SandboxCapacity.md) + - [Volcano::Generated::SandboxCapacityList](docs/SandboxCapacityList.md) + - [Volcano::Generated::SandboxCommandRequest](docs/SandboxCommandRequest.md) + - [Volcano::Generated::SandboxCommandResult](docs/SandboxCommandResult.md) + - [Volcano::Generated::SandboxDeployment](docs/SandboxDeployment.md) + - [Volcano::Generated::SandboxDeploymentPage](docs/SandboxDeploymentPage.md) + - [Volcano::Generated::SandboxExecutionRequest](docs/SandboxExecutionRequest.md) + - [Volcano::Generated::SandboxExecutionResult](docs/SandboxExecutionResult.md) + - [Volcano::Generated::SandboxFileReadRequest](docs/SandboxFileReadRequest.md) + - [Volcano::Generated::SandboxFileResult](docs/SandboxFileResult.md) + - [Volcano::Generated::SandboxFileWriteRequest](docs/SandboxFileWriteRequest.md) + - [Volcano::Generated::SandboxPagination](docs/SandboxPagination.md) + - [Volcano::Generated::SandboxPreset](docs/SandboxPreset.md) + - [Volcano::Generated::SandboxPresetList](docs/SandboxPresetList.md) + - [Volcano::Generated::SandboxSession](docs/SandboxSession.md) + - [Volcano::Generated::SandboxSessionPage](docs/SandboxSessionPage.md) + - [Volcano::Generated::SandboxSubjectGrantRequest](docs/SandboxSubjectGrantRequest.md) + - [Volcano::Generated::SandboxTemplate](docs/SandboxTemplate.md) + - [Volcano::Generated::SandboxTemplatePage](docs/SandboxTemplatePage.md) - [Volcano::Generated::ScheduleRequest](docs/ScheduleRequest.md) - [Volcano::Generated::ServiceKey](docs/ServiceKey.md) - [Volcano::Generated::SetProjectGitProductionBranchRequest](docs/SetProjectGitProductionBranchRequest.md) @@ -684,6 +771,7 @@ Class | Method | HTTP request | Description - [Volcano::Generated::UpdateProjectGitDeploySettingsRequest](docs/UpdateProjectGitDeploySettingsRequest.md) - [Volcano::Generated::UpdateProjectRequest](docs/UpdateProjectRequest.md) - [Volcano::Generated::UpdateRealtimeConfigRequest](docs/UpdateRealtimeConfigRequest.md) + - [Volcano::Generated::UpdateSandboxTemplateRequest](docs/UpdateSandboxTemplateRequest.md) - [Volcano::Generated::UpdateStorageBucketRequest](docs/UpdateStorageBucketRequest.md) - [Volcano::Generated::UpdateVariableRequest](docs/UpdateVariableRequest.md) - [Volcano::Generated::UploadSessionPart](docs/UploadSessionPart.md) @@ -711,5 +799,9 @@ Authentication schemes defined for the API: ### UserToken -- **Type**: Bearer authentication (JWT) +- **Type**: Bearer authentication (opaque) + +### ProjectAccessToken + +- **Type**: Bearer authentication (opaque) diff --git a/lib/volcano/generated/lib/volcano-generated.rb b/lib/volcano/generated/lib/volcano-generated.rb index 97b4f52b..7d9d69e0 100644 --- a/lib/volcano/generated/lib/volcano-generated.rb +++ b/lib/volcano/generated/lib/volcano-generated.rb @@ -78,6 +78,11 @@ Volcano::Generated.autoload :BanUserResponse, 'volcano-generated/models/ban_user_response' Volcano::Generated.autoload :BatchFunctionDeployFailure, 'volcano-generated/models/batch_function_deploy_failure' Volcano::Generated.autoload :BatchFunctionDeployResponse, 'volcano-generated/models/batch_function_deploy_response' +Volcano::Generated.autoload :CallMCP200Response, 'volcano-generated/models/call_mcp200_response' +Volcano::Generated.autoload :CallMCP200ResponseError, 'volcano-generated/models/call_mcp200_response_error' +Volcano::Generated.autoload :CallMCP200ResponseId, 'volcano-generated/models/call_mcp200_response_id' +Volcano::Generated.autoload :CallMCPRequest, 'volcano-generated/models/call_mcp_request' +Volcano::Generated.autoload :CallMCPRequestId, 'volcano-generated/models/call_mcp_request_id' Volcano::Generated.autoload :CallOAuthProviderAPI200Response, 'volcano-generated/models/call_o_auth_provider_api200_response' Volcano::Generated.autoload :CallOAuthProviderAPIRequest, 'volcano-generated/models/call_o_auth_provider_api_request' Volcano::Generated.autoload :CompleteUploadSessionResponse, 'volcano-generated/models/complete_upload_session_response' @@ -91,15 +96,20 @@ Volcano::Generated.autoload :CreateDatabaseRestoreRequest, 'volcano-generated/models/create_database_restore_request' Volcano::Generated.autoload :CreateEmailTemplateRequest, 'volcano-generated/models/create_email_template_request' Volcano::Generated.autoload :CreateFrontendCustomDomainRequest, 'volcano-generated/models/create_frontend_custom_domain_request' +Volcano::Generated.autoload :CreateFrontendFunctionRouteRequest, 'volcano-generated/models/create_frontend_function_route_request' Volcano::Generated.autoload :CreateFunctionSchedulerRequest, 'volcano-generated/models/create_function_scheduler_request' Volcano::Generated.autoload :CreateOAuthConfigRequest, 'volcano-generated/models/create_o_auth_config_request' +Volcano::Generated.autoload :CreateProjectAccessTokenRequest, 'volcano-generated/models/create_project_access_token_request' Volcano::Generated.autoload :CreateProjectRequest, 'volcano-generated/models/create_project_request' +Volcano::Generated.autoload :CreateSandboxSessionRequest, 'volcano-generated/models/create_sandbox_session_request' +Volcano::Generated.autoload :CreateSandboxTemplateRequest, 'volcano-generated/models/create_sandbox_template_request' Volcano::Generated.autoload :CreateServiceKeyRequest, 'volcano-generated/models/create_service_key_request' Volcano::Generated.autoload :CreateStorageBucketRequest, 'volcano-generated/models/create_storage_bucket_request' Volcano::Generated.autoload :CreateStoragePolicyRequest, 'volcano-generated/models/create_storage_policy_request' Volcano::Generated.autoload :CreateUploadSessionRequest, 'volcano-generated/models/create_upload_session_request' Volcano::Generated.autoload :CreateUploadSessionResponse, 'volcano-generated/models/create_upload_session_response' Volcano::Generated.autoload :CreateVariableRequest, 'volcano-generated/models/create_variable_request' +Volcano::Generated.autoload :CreatedProjectAccessToken, 'volcano-generated/models/created_project_access_token' Volcano::Generated.autoload :Database, 'volcano-generated/models/database' Volcano::Generated.autoload :DatabaseBackup, 'volcano-generated/models/database_backup' Volcano::Generated.autoload :DatabaseBackupList, 'volcano-generated/models/database_backup_list' @@ -133,6 +143,10 @@ Volcano::Generated.autoload :DeviceAuthorizationResponse, 'volcano-generated/models/device_authorization_response' Volcano::Generated.autoload :DurableExecution, 'volcano-generated/models/durable_execution' Volcano::Generated.autoload :DurableExecutionError, 'volcano-generated/models/durable_execution_error' +Volcano::Generated.autoload :DurableExecutionInvocation, 'volcano-generated/models/durable_execution_invocation' +Volcano::Generated.autoload :DurableExecutionOperation, 'volcano-generated/models/durable_execution_operation' +Volcano::Generated.autoload :DurableExecutionOperationAttempt, 'volcano-generated/models/durable_execution_operation_attempt' +Volcano::Generated.autoload :DurableExecutionOperationList, 'volcano-generated/models/durable_execution_operation_list' Volcano::Generated.autoload :DurableExecutionStatus, 'volcano-generated/models/durable_execution_status' Volcano::Generated.autoload :DurableFunction, 'volcano-generated/models/durable_function' Volcano::Generated.autoload :DurableFunctionConfig, 'volcano-generated/models/durable_function_config' @@ -145,6 +159,8 @@ Volcano::Generated.autoload :FrontendDeployment, 'volcano-generated/models/frontend_deployment' Volcano::Generated.autoload :FrontendDomainRoutingRecord, 'volcano-generated/models/frontend_domain_routing_record' Volcano::Generated.autoload :FrontendDomainVerificationRecord, 'volcano-generated/models/frontend_domain_verification_record' +Volcano::Generated.autoload :FrontendFunctionRoute, 'volcano-generated/models/frontend_function_route' +Volcano::Generated.autoload :FrontendFunctionRouteList, 'volcano-generated/models/frontend_function_route_list' Volcano::Generated.autoload :FrontendUsageDailyEntry, 'volcano-generated/models/frontend_usage_daily_entry' Volcano::Generated.autoload :FrontendUsageData, 'volcano-generated/models/frontend_usage_data' Volcano::Generated.autoload :FrontendUsageHistoryResponse, 'volcano-generated/models/frontend_usage_history_response' @@ -219,6 +235,7 @@ Volcano::Generated.autoload :PaginatedFrontends, 'volcano-generated/models/paginated_frontends' Volcano::Generated.autoload :PaginatedFunctionDeployments, 'volcano-generated/models/paginated_function_deployments' Volcano::Generated.autoload :PaginatedFunctions, 'volcano-generated/models/paginated_functions' +Volcano::Generated.autoload :PaginatedProjectAccessTokens, 'volcano-generated/models/paginated_project_access_tokens' Volcano::Generated.autoload :PaginatedProjectCustomDomains, 'volcano-generated/models/paginated_project_custom_domains' Volcano::Generated.autoload :PaginatedProjectDeployments, 'volcano-generated/models/paginated_project_deployments' Volcano::Generated.autoload :PaginatedProjects, 'volcano-generated/models/paginated_projects' @@ -229,6 +246,10 @@ Volcano::Generated.autoload :PreviewAuthPageRequest, 'volcano-generated/models/preview_auth_page_request' Volcano::Generated.autoload :PreviewAuthPageResponse, 'volcano-generated/models/preview_auth_page_response' Volcano::Generated.autoload :Project, 'volcano-generated/models/project' +Volcano::Generated.autoload :ProjectAccessToken, 'volcano-generated/models/project_access_token' +Volcano::Generated.autoload :ProjectAccessTokenScope, 'volcano-generated/models/project_access_token_scope' +Volcano::Generated.autoload :ProjectAccessTokenUsage, 'volcano-generated/models/project_access_token_usage' +Volcano::Generated.autoload :ProjectAccessTokenUsageDailyEntry, 'volcano-generated/models/project_access_token_usage_daily_entry' Volcano::Generated.autoload :ProjectConfig, 'volcano-generated/models/project_config' Volcano::Generated.autoload :ProjectConfigApplyResult, 'volcano-generated/models/project_config_apply_result' Volcano::Generated.autoload :ProjectConfigApplyResultEntry, 'volcano-generated/models/project_config_apply_result_entry' @@ -258,6 +279,7 @@ Volcano::Generated.autoload :ProjectConfigEmailTemplate, 'volcano-generated/models/project_config_email_template' Volcano::Generated.autoload :ProjectConfigEmailTemplates, 'volcano-generated/models/project_config_email_templates' Volcano::Generated.autoload :ProjectConfigFrontend, 'volcano-generated/models/project_config_frontend' +Volcano::Generated.autoload :ProjectConfigFrontendFunctionRoute, 'volcano-generated/models/project_config_frontend_function_route' Volcano::Generated.autoload :ProjectConfigFunction, 'volcano-generated/models/project_config_function' Volcano::Generated.autoload :ProjectConfigHostedPage, 'volcano-generated/models/project_config_hosted_page' Volcano::Generated.autoload :ProjectConfigHostedPages, 'volcano-generated/models/project_config_hosted_pages' @@ -324,14 +346,37 @@ Volcano::Generated.autoload :ProjectSourceExportSkip, 'volcano-generated/models/project_source_export_skip' Volcano::Generated.autoload :ProjectSourceExportState, 'volcano-generated/models/project_source_export_state' Volcano::Generated.autoload :ProjectUsageResponse, 'volcano-generated/models/project_usage_response' +Volcano::Generated.autoload :PublishSandboxPresetRequest, 'volcano-generated/models/publish_sandbox_preset_request' Volcano::Generated.autoload :RealtimeConfig, 'volcano-generated/models/realtime_config' Volcano::Generated.autoload :RealtimePlanLimits, 'volcano-generated/models/realtime_plan_limits' Volcano::Generated.autoload :RealtimeStats, 'volcano-generated/models/realtime_stats' Volcano::Generated.autoload :RefreshOAuthProviderToken200Response, 'volcano-generated/models/refresh_o_auth_provider_token200_response' +Volcano::Generated.autoload :ReplaceFrontendSharedVariablesRequest, 'volcano-generated/models/replace_frontend_shared_variables_request' Volcano::Generated.autoload :ReplaceSharedVariablesRequest, 'volcano-generated/models/replace_shared_variables_request' Volcano::Generated.autoload :ResetDatabasePassword200Response, 'volcano-generated/models/reset_database_password200_response' Volcano::Generated.autoload :ResolveFunctionResponse, 'volcano-generated/models/resolve_function_response' Volcano::Generated.autoload :ResourceReference, 'volcano-generated/models/resource_reference' +Volcano::Generated.autoload :SandboxAccess, 'volcano-generated/models/sandbox_access' +Volcano::Generated.autoload :SandboxAccessRequest, 'volcano-generated/models/sandbox_access_request' +Volcano::Generated.autoload :SandboxCapacity, 'volcano-generated/models/sandbox_capacity' +Volcano::Generated.autoload :SandboxCapacityList, 'volcano-generated/models/sandbox_capacity_list' +Volcano::Generated.autoload :SandboxCommandRequest, 'volcano-generated/models/sandbox_command_request' +Volcano::Generated.autoload :SandboxCommandResult, 'volcano-generated/models/sandbox_command_result' +Volcano::Generated.autoload :SandboxDeployment, 'volcano-generated/models/sandbox_deployment' +Volcano::Generated.autoload :SandboxDeploymentPage, 'volcano-generated/models/sandbox_deployment_page' +Volcano::Generated.autoload :SandboxExecutionRequest, 'volcano-generated/models/sandbox_execution_request' +Volcano::Generated.autoload :SandboxExecutionResult, 'volcano-generated/models/sandbox_execution_result' +Volcano::Generated.autoload :SandboxFileReadRequest, 'volcano-generated/models/sandbox_file_read_request' +Volcano::Generated.autoload :SandboxFileResult, 'volcano-generated/models/sandbox_file_result' +Volcano::Generated.autoload :SandboxFileWriteRequest, 'volcano-generated/models/sandbox_file_write_request' +Volcano::Generated.autoload :SandboxPagination, 'volcano-generated/models/sandbox_pagination' +Volcano::Generated.autoload :SandboxPreset, 'volcano-generated/models/sandbox_preset' +Volcano::Generated.autoload :SandboxPresetList, 'volcano-generated/models/sandbox_preset_list' +Volcano::Generated.autoload :SandboxSession, 'volcano-generated/models/sandbox_session' +Volcano::Generated.autoload :SandboxSessionPage, 'volcano-generated/models/sandbox_session_page' +Volcano::Generated.autoload :SandboxSubjectGrantRequest, 'volcano-generated/models/sandbox_subject_grant_request' +Volcano::Generated.autoload :SandboxTemplate, 'volcano-generated/models/sandbox_template' +Volcano::Generated.autoload :SandboxTemplatePage, 'volcano-generated/models/sandbox_template_page' Volcano::Generated.autoload :ScheduleRequest, 'volcano-generated/models/schedule_request' Volcano::Generated.autoload :ServiceKey, 'volcano-generated/models/service_key' Volcano::Generated.autoload :SetProjectGitProductionBranchRequest, 'volcano-generated/models/set_project_git_production_branch_request' @@ -360,6 +405,7 @@ Volcano::Generated.autoload :UpdateProjectGitDeploySettingsRequest, 'volcano-generated/models/update_project_git_deploy_settings_request' Volcano::Generated.autoload :UpdateProjectRequest, 'volcano-generated/models/update_project_request' Volcano::Generated.autoload :UpdateRealtimeConfigRequest, 'volcano-generated/models/update_realtime_config_request' +Volcano::Generated.autoload :UpdateSandboxTemplateRequest, 'volcano-generated/models/update_sandbox_template_request' Volcano::Generated.autoload :UpdateStorageBucketRequest, 'volcano-generated/models/update_storage_bucket_request' Volcano::Generated.autoload :UpdateVariableRequest, 'volcano-generated/models/update_variable_request' Volcano::Generated.autoload :UploadSessionPart, 'volcano-generated/models/upload_session_part' @@ -385,9 +431,11 @@ Volcano::Generated.autoload :LogsApi, 'volcano-generated/api/logs_api' Volcano::Generated.autoload :OAuthAuthenticationApi, 'volcano-generated/api/o_auth_authentication_api' Volcano::Generated.autoload :OAuthConfigurationApi, 'volcano-generated/api/o_auth_configuration_api' +Volcano::Generated.autoload :ProjectAccessTokensApi, 'volcano-generated/api/project_access_tokens_api' Volcano::Generated.autoload :ProjectImportsApi, 'volcano-generated/api/project_imports_api' Volcano::Generated.autoload :ProjectsApi, 'volcano-generated/api/projects_api' Volcano::Generated.autoload :RealtimeApi, 'volcano-generated/api/realtime_api' +Volcano::Generated.autoload :SandboxesApi, 'volcano-generated/api/sandboxes_api' Volcano::Generated.autoload :ServiceKeysApi, 'volcano-generated/api/service_keys_api' Volcano::Generated.autoload :StorageAdminApi, 'volcano-generated/api/storage_admin_api' Volcano::Generated.autoload :StorageBucketsApi, 'volcano-generated/api/storage_buckets_api' diff --git a/lib/volcano/generated/lib/volcano-generated/api/anon_keys_api.rb b/lib/volcano/generated/lib/volcano-generated/api/anon_keys_api.rb index b8e427fa..4663b2fa 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/anon_keys_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/anon_keys_api.rb @@ -72,7 +72,7 @@ def create_anon_key_with_http_info(id, create_anon_key_request, opts = {}) return_type = opts[:debug_return_type] || 'AnonKey' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AnonKeysApi.create_anon_key", @@ -141,7 +141,7 @@ def get_anon_key_with_http_info(id, key_id, opts = {}) return_type = opts[:debug_return_type] || 'AnonKey' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AnonKeysApi.get_anon_key", @@ -242,7 +242,7 @@ def list_anon_keys_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ListAnonKeys200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AnonKeysApi.list_anon_keys", @@ -311,7 +311,7 @@ def regenerate_anon_key_with_http_info(id, key_id, opts = {}) return_type = opts[:debug_return_type] || 'AnonKey' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AnonKeysApi.regenerate_anon_key", @@ -380,7 +380,7 @@ def revoke_anon_key_with_http_info(id, key_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AnonKeysApi.revoke_anon_key", @@ -449,7 +449,7 @@ def set_default_anon_key_with_http_info(id, key_id, opts = {}) return_type = opts[:debug_return_type] || 'AnonKey' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AnonKeysApi.set_default_anon_key", diff --git a/lib/volcano/generated/lib/volcano-generated/api/auth_admin_api.rb b/lib/volcano/generated/lib/volcano-generated/api/auth_admin_api.rb index b8dee32d..449606f4 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/auth_admin_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/auth_admin_api.rb @@ -76,7 +76,7 @@ def ban_auth_user_with_http_info(id, user_id, opts = {}) return_type = opts[:debug_return_type] || 'BanUserResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.ban_auth_user", @@ -143,7 +143,7 @@ def delete_all_user_sessions_with_http_info(id, user_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.delete_all_user_sessions", @@ -210,7 +210,7 @@ def delete_auth_user_with_http_info(id, user_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.delete_auth_user", @@ -283,7 +283,7 @@ def delete_user_session_with_http_info(id, user_id, session_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.delete_user_session", @@ -355,7 +355,7 @@ def get_auth_insights_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'AuthInsightsResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.get_auth_insights", @@ -422,7 +422,7 @@ def get_auth_user_with_http_info(id, user_id, opts = {}) return_type = opts[:debug_return_type] || 'AuthUser' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.get_auth_user", @@ -530,7 +530,7 @@ def list_auth_users_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedAuthUsers' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.list_auth_users", @@ -648,7 +648,7 @@ def list_user_sessions_with_http_info(id, user_id, opts = {}) return_type = opts[:debug_return_type] || 'AuthGetMySessions200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.list_user_sessions", @@ -717,7 +717,7 @@ def unban_auth_user_with_http_info(id, user_id, opts = {}) return_type = opts[:debug_return_type] || 'UnbanUserResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthAdminApi.unban_auth_user", diff --git a/lib/volcano/generated/lib/volcano-generated/api/auth_configuration_api.rb b/lib/volcano/generated/lib/volcano-generated/api/auth_configuration_api.rb index 83c72faf..1fdd74b0 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/auth_configuration_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/auth_configuration_api.rb @@ -68,7 +68,7 @@ def configure_auth_methods_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.configure_auth_methods", @@ -88,7 +88,7 @@ def configure_auth_methods_with_http_info(id, opts = {}) end # Create email template - # Creates a custom email template for the project. Custom email templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are rejected with 403, and HOBBY projects always send the built-in default templates regardless of any previously saved custom rows. Every project is created with one template per type, so customizing one is usually a PUT; creating a type the project already has returns 409. Valid template types: welcome, confirmation, password_reset, password_changed + # Creates a custom email template for the project. Custom email templates are a SUPERAGENT feature: requests from a HOBBY project owner are rejected with 403, and HOBBY projects always send the built-in default templates regardless of any previously saved custom rows. Every project is created with one template per type, so customizing one is usually a PUT; creating a type the project already has returns 409. Valid template types: welcome, confirmation, password_reset, password_changed # @param id [String] Project ID # @param create_email_template_request [CreateEmailTemplateRequest] # @param [Hash] opts the optional parameters @@ -99,7 +99,7 @@ def create_email_template(id, create_email_template_request, opts = {}) end # Create email template - # Creates a custom email template for the project. Custom email templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are rejected with 403, and HOBBY projects always send the built-in default templates regardless of any previously saved custom rows. Every project is created with one template per type, so customizing one is usually a PUT; creating a type the project already has returns 409. Valid template types: welcome, confirmation, password_reset, password_changed + # Creates a custom email template for the project. Custom email templates are a SUPERAGENT feature: requests from a HOBBY project owner are rejected with 403, and HOBBY projects always send the built-in default templates regardless of any previously saved custom rows. Every project is created with one template per type, so customizing one is usually a PUT; creating a type the project already has returns 409. Valid template types: welcome, confirmation, password_reset, password_changed # @param id [String] Project ID # @param create_email_template_request [CreateEmailTemplateRequest] # @param [Hash] opts the optional parameters @@ -142,7 +142,7 @@ def create_email_template_with_http_info(id, create_email_template_request, opts return_type = opts[:debug_return_type] || 'EmailTemplate' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.create_email_template", @@ -209,7 +209,7 @@ def delete_auth_page_layout_with_http_info(id, page_type, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.delete_auth_page_layout", @@ -270,7 +270,7 @@ def delete_auth_page_theme_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.delete_auth_page_theme", @@ -290,7 +290,7 @@ def delete_auth_page_theme_with_http_info(id, opts = {}) end # Delete email template - # Deletes a custom template, reverting to the default. Custom email templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are rejected with 403. + # Deletes a custom template, reverting to the default. Custom email templates are a SUPERAGENT feature: requests from a HOBBY project owner are rejected with 403. # @param id [String] Project ID # @param type [String] # @param [Hash] opts the optional parameters @@ -301,7 +301,7 @@ def delete_email_template(id, type, opts = {}) end # Delete email template - # Deletes a custom template, reverting to the default. Custom email templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are rejected with 403. + # Deletes a custom template, reverting to the default. Custom email templates are a SUPERAGENT feature: requests from a HOBBY project owner are rejected with 403. # @param id [String] Project ID # @param type [String] # @param [Hash] opts the optional parameters @@ -344,7 +344,7 @@ def delete_email_template_with_http_info(id, type, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.delete_email_template", @@ -405,7 +405,7 @@ def get_auth_config_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'AuthConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.get_auth_config", @@ -474,7 +474,7 @@ def get_auth_hosted_page_with_http_info(id, page_type, opts = {}) return_type = opts[:debug_return_type] || 'AuthHostedPageResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.get_auth_hosted_page", @@ -537,7 +537,7 @@ def get_auth_methods_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'GetAuthMethods200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.get_auth_methods", @@ -598,7 +598,7 @@ def get_auth_page_appearance_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'AuthPageAppearanceResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.get_auth_page_appearance", @@ -793,7 +793,7 @@ def get_email_template_with_http_info(id, type, opts = {}) return_type = opts[:debug_return_type] || 'EmailTemplate' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.get_email_template", @@ -1007,7 +1007,7 @@ def list_email_templates_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ListEmailTemplates200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.list_email_templates", @@ -1085,7 +1085,7 @@ def preview_auth_page_with_http_info(id, page_type, preview_auth_page_request, o return_type = opts[:debug_return_type] || 'PreviewAuthPageResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.preview_auth_page", @@ -1391,7 +1391,7 @@ def test_email_config_with_http_info(id, test_email_request, opts = {}) return_type = opts[:debug_return_type] || 'TestEmailResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.test_email_config", @@ -1461,7 +1461,7 @@ def update_auth_config_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'AuthConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.update_auth_config", @@ -1541,7 +1541,7 @@ def update_auth_hosted_page_with_http_info(id, page_type, update_auth_hosted_pag return_type = opts[:debug_return_type] || 'AuthHostedPageResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.update_auth_hosted_page", @@ -1619,7 +1619,7 @@ def update_auth_page_layout_with_http_info(id, page_type, update_auth_page_layou return_type = opts[:debug_return_type] || 'UpdateAuthPageLayoutRequest' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.update_auth_page_layout", @@ -1691,7 +1691,7 @@ def update_auth_page_theme_with_http_info(id, update_auth_page_theme_request, op return_type = opts[:debug_return_type] || 'UpdateAuthPageThemeRequest' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.update_auth_page_theme", @@ -1711,7 +1711,7 @@ def update_auth_page_theme_with_http_info(id, update_auth_page_theme_request, op end # Update email template - # Updates a custom email template. Custom email templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are rejected with 403 (including after a SUPERAGENT→HOBBY downgrade), so a HOBBY project cannot modify templates and always sends the built-in defaults. + # Updates a custom email template. Custom email templates are a SUPERAGENT feature: requests from a HOBBY project owner are rejected with 403 (including after a downgrade), so a HOBBY project cannot modify templates and always sends the built-in defaults. # @param id [String] Project ID # @param type [String] # @param update_email_template_request [UpdateEmailTemplateRequest] @@ -1723,7 +1723,7 @@ def update_email_template(id, type, update_email_template_request, opts = {}) end # Update email template - # Updates a custom email template. Custom email templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are rejected with 403 (including after a SUPERAGENT→HOBBY downgrade), so a HOBBY project cannot modify templates and always sends the built-in defaults. + # Updates a custom email template. Custom email templates are a SUPERAGENT feature: requests from a HOBBY project owner are rejected with 403 (including after a downgrade), so a HOBBY project cannot modify templates and always sends the built-in defaults. # @param id [String] Project ID # @param type [String] # @param update_email_template_request [UpdateEmailTemplateRequest] @@ -1776,7 +1776,7 @@ def update_email_template_with_http_info(id, type, update_email_template_request return_type = opts[:debug_return_type] || 'EmailTemplate' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"AuthConfigurationApi.update_email_template", diff --git a/lib/volcano/generated/lib/volcano-generated/api/authentication_api.rb b/lib/volcano/generated/lib/volcano-generated/api/authentication_api.rb index bf4d6123..756086d4 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/authentication_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/authentication_api.rb @@ -1194,7 +1194,7 @@ def auth_reset_password_with_http_info(auth_reset_password_request, opts = {}) end # Sign in an auth user - # Authenticate with email and password. Requires an anon key. Set `session_mode` to `cookie` to request HttpOnly refresh-token storage. Cookie mode is honored only for an exact, credentialed CORS origin on the same schemeful site as this API. Otherwise the response retains the refresh token in its body. + # Authenticate with email and password. Requires an anon key. Set `session_mode` to `cookie` to request HttpOnly refresh-token storage. Cookie mode is honored only for an exact, credentialed CORS origin on the same schemeful site as this API. Otherwise the response retains the refresh token in its body. A frontend on its default Volcano URL is cross-site with this API and so always gets the body token. # @param auth_signin_request [AuthSigninRequest] # @param [Hash] opts the optional parameters # @return [AuthTokenResponse] @@ -1204,7 +1204,7 @@ def auth_signin(auth_signin_request, opts = {}) end # Sign in an auth user - # Authenticate with email and password. Requires an anon key. Set `session_mode` to `cookie` to request HttpOnly refresh-token storage. Cookie mode is honored only for an exact, credentialed CORS origin on the same schemeful site as this API. Otherwise the response retains the refresh token in its body. + # Authenticate with email and password. Requires an anon key. Set `session_mode` to `cookie` to request HttpOnly refresh-token storage. Cookie mode is honored only for an exact, credentialed CORS origin on the same schemeful site as this API. Otherwise the response retains the refresh token in its body. A frontend on its default Volcano URL is cross-site with this API and so always gets the body token. # @param auth_signin_request [AuthSigninRequest] # @param [Hash] opts the optional parameters # @return [Array<(AuthTokenResponse, Integer, Hash)>] AuthTokenResponse data, response status code and response headers diff --git a/lib/volcano/generated/lib/volcano-generated/api/database_backups_api.rb b/lib/volcano/generated/lib/volcano-generated/api/database_backups_api.rb index b66ce73c..59351a1e 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/database_backups_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/database_backups_api.rb @@ -89,7 +89,7 @@ def create_database_backup_with_http_info(id, database_name, create_database_bac return_type = opts[:debug_return_type] || 'DatabaseBackup' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.create_database_backup", @@ -178,7 +178,7 @@ def create_database_restore_with_http_info(id, database_name, create_database_re return_type = opts[:debug_return_type] || 'DatabaseRestore' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.create_database_restore", @@ -270,7 +270,7 @@ def delete_database_backup_with_http_info(id, database_name, backup_name, opts = return_type = opts[:debug_return_type] || 'DeleteDatabaseBackup200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.delete_database_backup", @@ -362,7 +362,7 @@ def get_database_backup_with_http_info(id, database_name, backup_name, opts = {} return_type = opts[:debug_return_type] || 'DatabaseBackup' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.get_database_backup", @@ -440,7 +440,7 @@ def get_database_backup_schedule_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'DatabaseBackupSchedule' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.get_database_backup_schedule", @@ -524,7 +524,7 @@ def get_database_restore_with_http_info(id, database_name, restore_id, opts = {} return_type = opts[:debug_return_type] || 'DatabaseRestore' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.get_database_restore", @@ -602,7 +602,7 @@ def list_database_backups_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'DatabaseBackupList' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.list_database_backups", @@ -680,7 +680,7 @@ def list_database_restores_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'DatabaseRestoreList' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.list_database_restores", @@ -769,7 +769,7 @@ def update_database_backup_schedule_with_http_info(id, database_name, database_b return_type = opts[:debug_return_type] || 'DatabaseBackupSchedule' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBackupsApi.update_database_backup_schedule", diff --git a/lib/volcano/generated/lib/volcano-generated/api/database_branches_api.rb b/lib/volcano/generated/lib/volcano-generated/api/database_branches_api.rb index a4b740da..bf0584ed 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/database_branches_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/database_branches_api.rb @@ -89,7 +89,7 @@ def create_database_branch_with_http_info(id, database_name, create_database_bra return_type = opts[:debug_return_type] || 'DatabaseBranch' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBranchesApi.create_database_branch", @@ -182,7 +182,7 @@ def delete_database_branch_with_http_info(id, database_name, branch_name, opts = return_type = opts[:debug_return_type] || 'DeleteDatabaseBranch202Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBranchesApi.delete_database_branch", @@ -275,7 +275,7 @@ def get_database_branch_with_http_info(id, database_name, branch_name, opts = {} return_type = opts[:debug_return_type] || 'DatabaseBranch' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBranchesApi.get_database_branch", @@ -353,7 +353,7 @@ def list_database_branches_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'DatabaseBranchList' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBranchesApi.list_database_branches", @@ -446,7 +446,7 @@ def reset_database_branch_with_http_info(id, database_name, branch_name, opts = return_type = opts[:debug_return_type] || 'DatabaseBranch' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBranchesApi.reset_database_branch", @@ -539,7 +539,7 @@ def reset_database_branch_password_with_http_info(id, database_name, branch_name return_type = opts[:debug_return_type] || 'DatabaseBranch' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBranchesApi.reset_database_branch_password", @@ -643,7 +643,7 @@ def update_database_branch_with_http_info(id, database_name, branch_name, update return_type = opts[:debug_return_type] || 'DatabaseBranch' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabaseBranchesApi.update_database_branch", diff --git a/lib/volcano/generated/lib/volcano-generated/api/database_queries_api.rb b/lib/volcano/generated/lib/volcano-generated/api/database_queries_api.rb index f10bf25d..95b228e7 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/database_queries_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/database_queries_api.rb @@ -303,7 +303,7 @@ def query_database_branch_ping_with_http_info(database_name, branch_name, opts = end # Query database with SELECT (REST API) - # Query your database using a simple REST API - no SQL required! **Authentication:** Requires auth user access token (from signup/signin) **Row-Level Security:** Automatically enforced - you see only data you have access to **Use Cases:** - Query from browser/mobile apps - Simple data retrieval - Filtered searches with sorting and pagination **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL **Branch-targeted.** Runs against the named branch instead of the parent database, using the branch's own credentials. The branch must be `active` and unexpired. Nothing about this request can reach the parent's data. + # Query your database using a simple REST API - no SQL required! **Authentication:** Requires auth user access token (from signup/signin) **Row-Level Security:** Automatically enforced - you see only data you have access to **Use Cases:** - Query from browser/mobile apps - Simple data retrieval - Filtered searches with sorting and pagination **Note:** For complex queries (JOINs, CTEs), use a function with direct SQL **Branch-targeted.** Runs against the named branch instead of the parent database, using the branch's own credentials. The branch must be `active` and unexpired. Nothing about this request can reach the parent's data. # @param database_name [String] Database name (unique within project, lowercase letters, numbers, and underscores only) # @param branch_name [String] Branch name (unique within the parent database, lowercase letters, numbers, and underscores only) # @param database_select_request [DatabaseSelectRequest] @@ -315,7 +315,7 @@ def query_database_branch_select(database_name, branch_name, database_select_req end # Query database with SELECT (REST API) - # Query your database using a simple REST API - no SQL required! **Authentication:** Requires auth user access token (from signup/signin) **Row-Level Security:** Automatically enforced - you see only data you have access to **Use Cases:** - Query from browser/mobile apps - Simple data retrieval - Filtered searches with sorting and pagination **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL **Branch-targeted.** Runs against the named branch instead of the parent database, using the branch's own credentials. The branch must be `active` and unexpired. Nothing about this request can reach the parent's data. + # Query your database using a simple REST API - no SQL required! **Authentication:** Requires auth user access token (from signup/signin) **Row-Level Security:** Automatically enforced - you see only data you have access to **Use Cases:** - Query from browser/mobile apps - Simple data retrieval - Filtered searches with sorting and pagination **Note:** For complex queries (JOINs, CTEs), use a function with direct SQL **Branch-targeted.** Runs against the named branch instead of the parent database, using the branch's own credentials. The branch must be `active` and unexpired. Nothing about this request can reach the parent's data. # @param database_name [String] Database name (unique within project, lowercase letters, numbers, and underscores only) # @param branch_name [String] Branch name (unique within the parent database, lowercase letters, numbers, and underscores only) # @param database_select_request [DatabaseSelectRequest] diff --git a/lib/volcano/generated/lib/volcano-generated/api/databases_api.rb b/lib/volcano/generated/lib/volcano-generated/api/databases_api.rb index 3aa367a0..bf6908fb 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/databases_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/databases_api.rb @@ -19,8 +19,8 @@ class DatabasesApi def initialize(api_client = ApiClient.default) @api_client = api_client end - # Create a new serverless PostgreSQL database - # Creates a serverless PostgreSQL database in the project. Each project can hold 1 database on Hobby and up to 10,000 on Superagent. Requests over the plan's cap return 403. + # Create a new PostgreSQL database + # Creates a PostgreSQL database in the project. Each project can hold 1 database on HOBBY and up to 10,000 on SUPERAGENT. Requests over the plan's cap return 403. # @param id [String] Project ID # @param create_database_request [CreateDatabaseRequest] # @param [Hash] opts the optional parameters @@ -30,8 +30,8 @@ def create_database(id, create_database_request, opts = {}) data end - # Create a new serverless PostgreSQL database - # Creates a serverless PostgreSQL database in the project. Each project can hold 1 database on Hobby and up to 10,000 on Superagent. Requests over the plan's cap return 403. + # Create a new PostgreSQL database + # Creates a PostgreSQL database in the project. Each project can hold 1 database on HOBBY and up to 10,000 on SUPERAGENT. Requests over the plan's cap return 403. # @param id [String] Project ID # @param create_database_request [CreateDatabaseRequest] # @param [Hash] opts the optional parameters @@ -74,7 +74,7 @@ def create_database_with_http_info(id, create_database_request, opts = {}) return_type = opts[:debug_return_type] || 'Database' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.create_database", @@ -152,7 +152,7 @@ def delete_database_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'DeleteDatabase202Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.delete_database", @@ -228,7 +228,7 @@ def get_database_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'Database' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.get_database", @@ -319,7 +319,7 @@ def get_database_stats_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'DatabaseStats' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.get_database_stats", @@ -339,7 +339,7 @@ def get_database_stats_with_http_info(id, database_name, opts = {}) end # Get database queries - # Returns the database's current top queries from pg_stat_statements ranked by total execution time. **SUPERAGENT plan required.** This endpoint is only available to projects owned by users on the SUPERAGENT billing plan. + # Returns the database's current top queries from pg_stat_statements ranked by total execution time. Only data statements (SELECT, INSERT, UPDATE, DELETE, MERGE) are listed; statements Volcano runs to operate the database are left out. **SUPERAGENT plan required.** This endpoint is only available to projects owned by users on the SUPERAGENT billing plan. # @param id [String] Project ID # @param database_name [String] Database name (unique within project, lowercase letters, numbers, and underscores only) # @param [Hash] opts the optional parameters @@ -351,7 +351,7 @@ def get_project_database_queries(id, database_name, opts = {}) end # Get database queries - # Returns the database's current top queries from pg_stat_statements ranked by total execution time. **SUPERAGENT plan required.** This endpoint is only available to projects owned by users on the SUPERAGENT billing plan. + # Returns the database's current top queries from pg_stat_statements ranked by total execution time. Only data statements (SELECT, INSERT, UPDATE, DELETE, MERGE) are listed; statements Volcano runs to operate the database are left out. **SUPERAGENT plan required.** This endpoint is only available to projects owned by users on the SUPERAGENT billing plan. # @param id [String] Project ID # @param database_name [String] Database name (unique within project, lowercase letters, numbers, and underscores only) # @param [Hash] opts the optional parameters @@ -408,7 +408,7 @@ def get_project_database_queries_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'DatabaseQueryPerformanceResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.get_project_database_queries", @@ -573,7 +573,7 @@ def list_databases_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedDatabases' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.list_databases", @@ -708,7 +708,7 @@ def reset_database_password_with_http_info(id, database_name, opts = {}) return_type = opts[:debug_return_type] || 'ResetDatabasePassword200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.reset_database_password", @@ -797,7 +797,7 @@ def update_database_type_with_http_info(id, database_name, update_database_type_ return_type = opts[:debug_return_type] || 'Database' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"DatabasesApi.update_database_type", diff --git a/lib/volcano/generated/lib/volcano-generated/api/durable_functions_api.rb b/lib/volcano/generated/lib/volcano-generated/api/durable_functions_api.rb index aa672edb..6f55d35c 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/durable_functions_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/durable_functions_api.rb @@ -219,7 +219,7 @@ def create_durable_function_scheduler_with_http_info(id, function_id, create_fun end # Delete a durable function - # Accepted for asynchronous teardown; the work continues after the response. The function's executions go with it: history stops being readable whatever `retention_days` had left, and the executions still running stop counting against the project's concurrency cap. Stop an execution first if you need it to end before the function does. + # Accepted for asynchronous teardown; the work continues after the response. The function's executions go with it: executions still in flight are stopped, and history stops being readable whatever `retention_days` had left. Stopping is asynchronous at the platform, and it does not interrupt a step already running -- that step runs to its next checkpoint. So a delete ends an execution rather than halting it mid-step; stop the execution yourself first if you need to observe it ending. # @param id [String] Project ID # @param function_id [String] Durable function ID, or its name within the project # @param [Hash] opts the optional parameters @@ -230,7 +230,7 @@ def delete_durable_function(id, function_id, opts = {}) end # Delete a durable function - # Accepted for asynchronous teardown; the work continues after the response. The function's executions go with it: history stops being readable whatever `retention_days` had left, and the executions still running stop counting against the project's concurrency cap. Stop an execution first if you need it to end before the function does. + # Accepted for asynchronous teardown; the work continues after the response. The function's executions go with it: executions still in flight are stopped, and history stops being readable whatever `retention_days` had left. Stopping is asynchronous at the platform, and it does not interrupt a step already running -- that step runs to its next checkpoint. So a delete ends an execution rather than halting it mid-step; stop the execution yourself first if you need to observe it ending. # @param id [String] Project ID # @param function_id [String] Durable function ID, or its name within the project # @param [Hash] opts the optional parameters @@ -575,6 +575,81 @@ def get_durable_function_scheduler_with_http_info(id, function_id, scheduler_id, return data, status_code, headers end + # List a durable execution's operations + # Returns the execution's trace: every operation it began — each step, wait, poll, child context, map item and parallel branch — with when it started and ended, how it ended, and each attempt of a retried step. `invocations` are the windows the function's code was actually running; the gaps between them are time the execution spent suspended, which is not charged. A finished execution's trace is final and `complete` is `true`. A running one is refreshed when it is read, and can be up to about ten seconds behind; `synced_at` says when it was last refreshed. Inputs, results and other payloads are never included. The list is not paginated: an execution is limited to 3,000 operations, and a trace is read whole. + # @param id [String] Project ID + # @param function_id [String] Durable function ID, or its name within the project + # @param execution_id [String] Durable execution ID + # @param [Hash] opts the optional parameters + # @return [DurableExecutionOperationList] + def list_durable_execution_operations(id, function_id, execution_id, opts = {}) + data, _status_code, _headers = list_durable_execution_operations_with_http_info(id, function_id, execution_id, opts) + data + end + + # List a durable execution's operations + # Returns the execution's trace: every operation it began — each step, wait, poll, child context, map item and parallel branch — with when it started and ended, how it ended, and each attempt of a retried step. `invocations` are the windows the function's code was actually running; the gaps between them are time the execution spent suspended, which is not charged. A finished execution's trace is final and `complete` is `true`. A running one is refreshed when it is read, and can be up to about ten seconds behind; `synced_at` says when it was last refreshed. Inputs, results and other payloads are never included. The list is not paginated: an execution is limited to 3,000 operations, and a trace is read whole. + # @param id [String] Project ID + # @param function_id [String] Durable function ID, or its name within the project + # @param execution_id [String] Durable execution ID + # @param [Hash] opts the optional parameters + # @return [Array<(DurableExecutionOperationList, Integer, Hash)>] DurableExecutionOperationList data, response status code and response headers + def list_durable_execution_operations_with_http_info(id, function_id, execution_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: DurableFunctionsApi.list_durable_execution_operations ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling DurableFunctionsApi.list_durable_execution_operations" + end + # verify the required parameter 'function_id' is set + if @api_client.config.client_side_validation && function_id.nil? + fail ArgumentError, "Missing the required parameter 'function_id' when calling DurableFunctionsApi.list_durable_execution_operations" + end + # verify the required parameter 'execution_id' is set + if @api_client.config.client_side_validation && execution_id.nil? + fail ArgumentError, "Missing the required parameter 'execution_id' when calling DurableFunctionsApi.list_durable_execution_operations" + end + # resource path + local_var_path = '/projects/{id}/durable-functions/{functionId}/executions/{executionId}/operations'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'functionId' + '}', CGI.escape(function_id.to_s)).sub('{' + 'executionId' + '}', CGI.escape(execution_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'DurableExecutionOperationList' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken'] + + new_options = opts.merge( + :operation => :"DurableFunctionsApi.list_durable_execution_operations", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: DurableFunctionsApi#list_durable_execution_operations\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + # List a durable function's executions # Returns the platform's last observed status for each execution; listing does not poll each one. Fetch a single execution for its live state. # @param id [String] Project ID diff --git a/lib/volcano/generated/lib/volcano-generated/api/frontends_api.rb b/lib/volcano/generated/lib/volcano-generated/api/frontends_api.rb index ab864b85..5261b843 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/frontends_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/frontends_api.rb @@ -20,13 +20,15 @@ def initialize(api_client = ApiClient.default) @api_client = api_client end # Create a new frontend deployment - # Creates and deploys a frontend for the project. If a frontend with the same name already exists in the project, this operation updates that frontend using the uploaded archive and starts a new deployment. A deployment that starts immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or `failed`. If another deployment is running, the response preserves the frontend's current status and exposes the queued deployment through `pending_deployment_id`. Existing frontend traffic continues to use an available runtime while the new deployment builds and provisions. Each deployment publishes its own static assets before the runtimes switch to its build, and the live build's assets keep serving until the new deployment is live, so a page loaded mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes back on the build they were running, leaves the frontend `active` on the previous deployment, and records the attempted deployment as failed. `degraded` means the runtime remains available but edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a given frontend, while independent frontends and projects can deploy concurrently. For monorepos, provide `app_root` as a relative path from the uploaded archive root to the Next.js app that should be built. Omit it for single-app archives. Supported frontend environments are Next.js 15.x and 16.x with Node.js 22.x or 24.x. The Node.js runtime is inferred from `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x. The selected Node.js family must also satisfy the installed Next.js package's `engines.node` constraint. Volcano tests Next 15.5.25 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.5 (`>=20.9.0`). Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container images are built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`). Each project can contain up to 10,000 frontends regardless of plan. + # Creates and deploys a frontend for the project. If a frontend with the same name already exists in the project, this operation updates that frontend using the uploaded archive and starts a new deployment. A deployment that starts immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or `failed`. If another deployment is running, the response preserves the frontend's current status and exposes the queued deployment through `pending_deployment_id`. Existing frontend traffic continues to use an available runtime while the new deployment builds and provisions. Each deployment publishes its own static assets before the runtimes switch to its build, and the live build's assets keep serving until the new deployment is live, so a page loaded mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes back on the build they were running, leaves the frontend `active` on the previous deployment, and records the attempted deployment as failed. `degraded` means the runtime remains available but edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a given frontend, while independent frontends and projects can deploy concurrently. For monorepos, provide `app_root` as a relative path from the uploaded archive root to the Next.js app that should be built. Omit it for single-app archives. Supported frontend environments are Next.js 15.x and 16.x with Node.js 22.x or 24.x. The Node.js runtime is inferred from `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x. The selected Node.js family must also satisfy the installed Next.js package's `engines.node` constraint. Volcano tests Next 15.5.26 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.6 (`>=20.9.0`). Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container images are built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`). Each project can contain up to 10,000 frontends regardless of plan. # @param id [String] Project ID # @param name [String] DNS-safe frontend name # @param archive [File] ZIP or tar.gz archive of the frontend project directory or monorepo workspace root. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz archive. # @param [Hash] opts the optional parameters # @option opts [String] :framework Next.js frontend. Supported Next.js majors are 15.x and 16.x. (default to 'nextjs') # @option opts [String] :app_root Optional relative POSIX path from the uploaded archive root to the Next.js app to build, for example `apps/web`. + # @option opts [String] :variable_scope Variable selection for this deployment. New frontends default to `scoped`; omitting this field for an existing frontend preserves its current selection. + # @option opts [Array] :variables Project variable names selected when `variable_scope` is `scoped`. Submit each name as a repeated multipart field. # @return [Frontend] def create_frontend(id, name, archive, opts = {}) data, _status_code, _headers = create_frontend_with_http_info(id, name, archive, opts) @@ -34,13 +36,15 @@ def create_frontend(id, name, archive, opts = {}) end # Create a new frontend deployment - # Creates and deploys a frontend for the project. If a frontend with the same name already exists in the project, this operation updates that frontend using the uploaded archive and starts a new deployment. A deployment that starts immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or `failed`. If another deployment is running, the response preserves the frontend's current status and exposes the queued deployment through `pending_deployment_id`. Existing frontend traffic continues to use an available runtime while the new deployment builds and provisions. Each deployment publishes its own static assets before the runtimes switch to its build, and the live build's assets keep serving until the new deployment is live, so a page loaded mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes back on the build they were running, leaves the frontend `active` on the previous deployment, and records the attempted deployment as failed. `degraded` means the runtime remains available but edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a given frontend, while independent frontends and projects can deploy concurrently. For monorepos, provide `app_root` as a relative path from the uploaded archive root to the Next.js app that should be built. Omit it for single-app archives. Supported frontend environments are Next.js 15.x and 16.x with Node.js 22.x or 24.x. The Node.js runtime is inferred from `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x. The selected Node.js family must also satisfy the installed Next.js package's `engines.node` constraint. Volcano tests Next 15.5.25 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.5 (`>=20.9.0`). Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container images are built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`). Each project can contain up to 10,000 frontends regardless of plan. + # Creates and deploys a frontend for the project. If a frontend with the same name already exists in the project, this operation updates that frontend using the uploaded archive and starts a new deployment. A deployment that starts immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or `failed`. If another deployment is running, the response preserves the frontend's current status and exposes the queued deployment through `pending_deployment_id`. Existing frontend traffic continues to use an available runtime while the new deployment builds and provisions. Each deployment publishes its own static assets before the runtimes switch to its build, and the live build's assets keep serving until the new deployment is live, so a page loaded mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes back on the build they were running, leaves the frontend `active` on the previous deployment, and records the attempted deployment as failed. `degraded` means the runtime remains available but edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a given frontend, while independent frontends and projects can deploy concurrently. For monorepos, provide `app_root` as a relative path from the uploaded archive root to the Next.js app that should be built. Omit it for single-app archives. Supported frontend environments are Next.js 15.x and 16.x with Node.js 22.x or 24.x. The Node.js runtime is inferred from `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x. The selected Node.js family must also satisfy the installed Next.js package's `engines.node` constraint. Volcano tests Next 15.5.26 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.6 (`>=20.9.0`). Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container images are built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`). Each project can contain up to 10,000 frontends regardless of plan. # @param id [String] Project ID # @param name [String] DNS-safe frontend name # @param archive [File] ZIP or tar.gz archive of the frontend project directory or monorepo workspace root. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz archive. # @param [Hash] opts the optional parameters # @option opts [String] :framework Next.js frontend. Supported Next.js majors are 15.x and 16.x. (default to 'nextjs') # @option opts [String] :app_root Optional relative POSIX path from the uploaded archive root to the Next.js app to build, for example `apps/web`. + # @option opts [String] :variable_scope Variable selection for this deployment. New frontends default to `scoped`; omitting this field for an existing frontend preserves its current selection. + # @option opts [Array] :variables Project variable names selected when `variable_scope` is `scoped`. Submit each name as a repeated multipart field. # @return [Array<(Frontend, Integer, Hash)>] Frontend data, response status code and response headers def create_frontend_with_http_info(id, name, archive, opts = {}) if @api_client.config.debugging @@ -75,6 +79,10 @@ def create_frontend_with_http_info(id, name, archive, opts = {}) fail ArgumentError, 'invalid value for "opts[:"app_root"]" when calling FrontendsApi.create_frontend, the character length must be smaller than or equal to 1024.' end + allowable_values = ["all", "scoped"] + if @api_client.config.client_side_validation && opts[:'variable_scope'] && !allowable_values.include?(opts[:'variable_scope']) + fail ArgumentError, "invalid value for \"variable_scope\", must be one of #{allowable_values}" + end # resource path local_var_path = '/projects/{id}/frontends'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) @@ -97,6 +105,8 @@ def create_frontend_with_http_info(id, name, archive, opts = {}) form_params['archive'] = archive form_params['framework'] = opts[:'framework'] if !opts[:'framework'].nil? form_params['app_root'] = opts[:'app_root'] if !opts[:'app_root'].nil? + form_params['variable_scope'] = opts[:'variable_scope'] if !opts[:'variable_scope'].nil? + form_params['variables'] = @api_client.build_collection_param(opts[:'variables'], :csv) if !opts[:'variables'].nil? # http body (model) post_body = opts[:debug_body] @@ -105,7 +115,7 @@ def create_frontend_with_http_info(id, name, archive, opts = {}) return_type = opts[:debug_return_type] || 'Frontend' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.create_frontend", @@ -185,7 +195,7 @@ def create_frontend_custom_domain_with_http_info(id, frontend_id, create_fronten return_type = opts[:debug_return_type] || 'FrontendCustomDomainResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.create_frontend_custom_domain", @@ -204,6 +214,86 @@ def create_frontend_custom_domain_with_http_info(id, frontend_id, create_fronten return data, status_code, headers end + # Route a Frontend path to an HTTP Function + # The Frontend and Function must belong to this Project. The Function may be private but must use HTTP invocation mode. The route applies to every hostname that resolves to the Frontend, including generated, custom-domain, preview, and local hostnames. + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param create_frontend_function_route_request [CreateFrontendFunctionRouteRequest] + # @param [Hash] opts the optional parameters + # @return [FrontendFunctionRoute] + def create_frontend_function_route(id, frontend_id, create_frontend_function_route_request, opts = {}) + data, _status_code, _headers = create_frontend_function_route_with_http_info(id, frontend_id, create_frontend_function_route_request, opts) + data + end + + # Route a Frontend path to an HTTP Function + # The Frontend and Function must belong to this Project. The Function may be private but must use HTTP invocation mode. The route applies to every hostname that resolves to the Frontend, including generated, custom-domain, preview, and local hostnames. + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param create_frontend_function_route_request [CreateFrontendFunctionRouteRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(FrontendFunctionRoute, Integer, Hash)>] FrontendFunctionRoute data, response status code and response headers + def create_frontend_function_route_with_http_info(id, frontend_id, create_frontend_function_route_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: FrontendsApi.create_frontend_function_route ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling FrontendsApi.create_frontend_function_route" + end + # verify the required parameter 'frontend_id' is set + if @api_client.config.client_side_validation && frontend_id.nil? + fail ArgumentError, "Missing the required parameter 'frontend_id' when calling FrontendsApi.create_frontend_function_route" + end + # verify the required parameter 'create_frontend_function_route_request' is set + if @api_client.config.client_side_validation && create_frontend_function_route_request.nil? + fail ArgumentError, "Missing the required parameter 'create_frontend_function_route_request' when calling FrontendsApi.create_frontend_function_route" + end + # resource path + local_var_path = '/projects/{id}/frontends/{frontendId}/function-routes'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'frontendId' + '}', CGI.escape(frontend_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(create_frontend_function_route_request) + + # return_type + return_type = opts[:debug_return_type] || 'FrontendFunctionRoute' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] + + new_options = opts.merge( + :operation => :"FrontendsApi.create_frontend_function_route", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: FrontendsApi#create_frontend_function_route\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + # Delete a frontend # Schedules asynchronous frontend deletion. If another deployment is running, the frontend preserves its current status and exposes the queued deletion through `pending_deployment_id`. Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no longer appears in frontend lists. # @param id [String] Project ID @@ -254,7 +344,7 @@ def delete_frontend_with_http_info(id, frontend_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.delete_frontend", @@ -321,7 +411,7 @@ def delete_frontend_custom_domain_with_http_info(id, frontend_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.delete_frontend_custom_domain", @@ -340,6 +430,79 @@ def delete_frontend_custom_domain_with_http_info(id, frontend_id, opts = {}) return data, status_code, headers end + # Delete a Frontend Function route + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param route_id [String] Frontend Function route ID + # @param [Hash] opts the optional parameters + # @return [nil] + def delete_frontend_function_route(id, frontend_id, route_id, opts = {}) + delete_frontend_function_route_with_http_info(id, frontend_id, route_id, opts) + nil + end + + # Delete a Frontend Function route + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param route_id [String] Frontend Function route ID + # @param [Hash] opts the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def delete_frontend_function_route_with_http_info(id, frontend_id, route_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: FrontendsApi.delete_frontend_function_route ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling FrontendsApi.delete_frontend_function_route" + end + # verify the required parameter 'frontend_id' is set + if @api_client.config.client_side_validation && frontend_id.nil? + fail ArgumentError, "Missing the required parameter 'frontend_id' when calling FrontendsApi.delete_frontend_function_route" + end + # verify the required parameter 'route_id' is set + if @api_client.config.client_side_validation && route_id.nil? + fail ArgumentError, "Missing the required parameter 'route_id' when calling FrontendsApi.delete_frontend_function_route" + end + # resource path + local_var_path = '/projects/{id}/frontends/{frontendId}/function-routes/{routeId}'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'frontendId' + '}', CGI.escape(frontend_id.to_s)).sub('{' + 'routeId' + '}', CGI.escape(route_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] + + new_options = opts.merge( + :operation => :"FrontendsApi.delete_frontend_function_route", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: FrontendsApi#delete_frontend_function_route\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + # Get frontend details # @param id [String] Project ID # @param frontend_id [String] Frontend ID @@ -388,7 +551,7 @@ def get_frontend_with_http_info(id, frontend_id, opts = {}) return_type = opts[:debug_return_type] || 'Frontend' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.get_frontend", @@ -455,7 +618,7 @@ def get_frontend_custom_domain_with_http_info(id, frontend_id, opts = {}) return_type = opts[:debug_return_type] || 'FrontendCustomDomainResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.get_frontend_custom_domain", @@ -535,7 +698,7 @@ def get_frontend_usage_history_with_http_info(id, frontend_id, opts = {}) return_type = opts[:debug_return_type] || 'FrontendUsageHistoryResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.get_frontend_usage_history", @@ -620,7 +783,7 @@ def list_frontend_deployments_with_http_info(id, frontend_id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedFrontendDeployments' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.list_frontend_deployments", @@ -639,6 +802,73 @@ def list_frontend_deployments_with_http_info(id, frontend_id, opts = {}) return data, status_code, headers end + # List a Frontend's Function routes + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param [Hash] opts the optional parameters + # @return [FrontendFunctionRouteList] + def list_frontend_function_routes(id, frontend_id, opts = {}) + data, _status_code, _headers = list_frontend_function_routes_with_http_info(id, frontend_id, opts) + data + end + + # List a Frontend's Function routes + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param [Hash] opts the optional parameters + # @return [Array<(FrontendFunctionRouteList, Integer, Hash)>] FrontendFunctionRouteList data, response status code and response headers + def list_frontend_function_routes_with_http_info(id, frontend_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: FrontendsApi.list_frontend_function_routes ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling FrontendsApi.list_frontend_function_routes" + end + # verify the required parameter 'frontend_id' is set + if @api_client.config.client_side_validation && frontend_id.nil? + fail ArgumentError, "Missing the required parameter 'frontend_id' when calling FrontendsApi.list_frontend_function_routes" + end + # resource path + local_var_path = '/projects/{id}/frontends/{frontendId}/function-routes'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'frontendId' + '}', CGI.escape(frontend_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'FrontendFunctionRouteList' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] + + new_options = opts.merge( + :operation => :"FrontendsApi.list_frontend_function_routes", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: FrontendsApi#list_frontend_function_routes\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + # List all frontends in a project # Supports two mutually exclusive pagination modes. Offset mode uses `page` and `limit` and returns `next` (URL). Cursor mode uses `cursor` and `limit`, supports `search` (case-insensitive name match), and returns `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`) returns 400. # @param id [String] Project ID @@ -721,7 +951,7 @@ def list_frontends_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedFrontends' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.list_frontends", @@ -822,7 +1052,7 @@ def list_project_custom_domains_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedProjectCustomDomains' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.list_project_custom_domains", @@ -891,7 +1121,7 @@ def redeploy_frontend_with_http_info(id, frontend_id, opts = {}) return_type = opts[:debug_return_type] || 'Frontend' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FrontendsApi.redeploy_frontend", @@ -909,5 +1139,89 @@ def redeploy_frontend_with_http_info(id, frontend_id, opts = {}) end return data, status_code, headers end + + # Replace a Frontend Function route + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param route_id [String] Frontend Function route ID + # @param create_frontend_function_route_request [CreateFrontendFunctionRouteRequest] + # @param [Hash] opts the optional parameters + # @return [FrontendFunctionRoute] + def update_frontend_function_route(id, frontend_id, route_id, create_frontend_function_route_request, opts = {}) + data, _status_code, _headers = update_frontend_function_route_with_http_info(id, frontend_id, route_id, create_frontend_function_route_request, opts) + data + end + + # Replace a Frontend Function route + # @param id [String] Project ID + # @param frontend_id [String] Frontend ID + # @param route_id [String] Frontend Function route ID + # @param create_frontend_function_route_request [CreateFrontendFunctionRouteRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(FrontendFunctionRoute, Integer, Hash)>] FrontendFunctionRoute data, response status code and response headers + def update_frontend_function_route_with_http_info(id, frontend_id, route_id, create_frontend_function_route_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: FrontendsApi.update_frontend_function_route ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling FrontendsApi.update_frontend_function_route" + end + # verify the required parameter 'frontend_id' is set + if @api_client.config.client_side_validation && frontend_id.nil? + fail ArgumentError, "Missing the required parameter 'frontend_id' when calling FrontendsApi.update_frontend_function_route" + end + # verify the required parameter 'route_id' is set + if @api_client.config.client_side_validation && route_id.nil? + fail ArgumentError, "Missing the required parameter 'route_id' when calling FrontendsApi.update_frontend_function_route" + end + # verify the required parameter 'create_frontend_function_route_request' is set + if @api_client.config.client_side_validation && create_frontend_function_route_request.nil? + fail ArgumentError, "Missing the required parameter 'create_frontend_function_route_request' when calling FrontendsApi.update_frontend_function_route" + end + # resource path + local_var_path = '/projects/{id}/frontends/{frontendId}/function-routes/{routeId}'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'frontendId' + '}', CGI.escape(frontend_id.to_s)).sub('{' + 'routeId' + '}', CGI.escape(route_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(create_frontend_function_route_request) + + # return_type + return_type = opts[:debug_return_type] || 'FrontendFunctionRoute' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] + + new_options = opts.merge( + :operation => :"FrontendsApi.update_frontend_function_route", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:PUT, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: FrontendsApi#update_frontend_function_route\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end end end diff --git a/lib/volcano/generated/lib/volcano-generated/api/functions_api.rb b/lib/volcano/generated/lib/volcano-generated/api/functions_api.rb index 0885591f..4b50a2cf 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/functions_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/functions_api.rb @@ -20,7 +20,7 @@ def initialize(api_client = ApiClient.default) @api_client = api_client end # Create or update function code - # Upload a serverless function source bundle. Direct API clients may send the function code as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz source archive. Cloud deploys should include source files and dependency manifests/lockfiles, not installed dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the function compile build. Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container image is built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. Uploaded source archives cannot contain symlink entries. Safe symlinks created during the cloud build are materialized before publish. Volcano builds and deploys the function asynchronously after upload. A deployment that starts immediately returns a Function resource with `status: provisioning`, then transitions to `active` or `failed`. If another deployment is running, the response preserves the resource's current status and exposes the queued deployment through `pending_deployment_id`. Existing function traffic continues to use the last known-good runtime during an update. A failed update keeps that runtime available and records the attempted deployment as failed. Only one deployment runs for a given function. A newer request supersedes any queued request and starts after the running deployment. Different functions and projects deploy concurrently. If a function with the same name already exists in the project, this operation updates that function's runtime, handler, and source bundle and returns `200 OK`. Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403. + # Upload a function source bundle. Direct API clients may send the function code as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz source archive. Cloud deploys should include source files and dependency manifests/lockfiles, not installed dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the function compile build. Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container image is built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. Uploaded source archives cannot contain symlink entries. Safe symlinks created during the cloud build are materialized before publish. Volcano builds and deploys the function asynchronously after upload. A deployment that starts immediately returns a Function resource with `status: provisioning`, then transitions to `active` or `failed`. If another deployment is running, the response preserves the resource's current status and exposes the queued deployment through `pending_deployment_id`. Existing function traffic continues to use the last known-good runtime during an update. A failed update keeps that runtime available and records the attempted deployment as failed. Only one deployment runs for a given function. A newer request supersedes any queued request and starts after the running deployment. Different functions and projects deploy concurrently. If a function with the same name already exists in the project, this operation updates that function's runtime, handler, and source bundle and returns `200 OK`. Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403. # @param id [String] Project ID # @param name [String] DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) # @param code [File] ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz source archive. @@ -40,7 +40,7 @@ def create_function(id, name, code, runtime, opts = {}) end # Create or update function code - # Upload a serverless function source bundle. Direct API clients may send the function code as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz source archive. Cloud deploys should include source files and dependency manifests/lockfiles, not installed dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the function compile build. Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container image is built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. Uploaded source archives cannot contain symlink entries. Safe symlinks created during the cloud build are materialized before publish. Volcano builds and deploys the function asynchronously after upload. A deployment that starts immediately returns a Function resource with `status: provisioning`, then transitions to `active` or `failed`. If another deployment is running, the response preserves the resource's current status and exposes the queued deployment through `pending_deployment_id`. Existing function traffic continues to use the last known-good runtime during an update. A failed update keeps that runtime available and records the attempted deployment as failed. Only one deployment runs for a given function. A newer request supersedes any queued request and starts after the running deployment. Different functions and projects deploy concurrently. If a function with the same name already exists in the project, this operation updates that function's runtime, handler, and source bundle and returns `200 OK`. Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403. + # Upload a function source bundle. Direct API clients may send the function code as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz source archive. Cloud deploys should include source files and dependency manifests/lockfiles, not installed dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the function compile build. Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI does not apply its own source archive size limit. After the final container image is built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. Uploaded source archives cannot contain symlink entries. Safe symlinks created during the cloud build are materialized before publish. Volcano builds and deploys the function asynchronously after upload. A deployment that starts immediately returns a Function resource with `status: provisioning`, then transitions to `active` or `failed`. If another deployment is running, the response preserves the resource's current status and exposes the queued deployment through `pending_deployment_id`. Existing function traffic continues to use the last known-good runtime during an update. A failed update keeps that runtime available and records the attempted deployment as failed. Only one deployment runs for a given function. A newer request supersedes any queued request and starts after the running deployment. Different functions and projects deploy concurrently. If a function with the same name already exists in the project, this operation updates that function's runtime, handler, and source bundle and returns `200 OK`. Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403. # @param id [String] Project ID # @param name [String] DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) # @param code [File] ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz source archive. @@ -128,7 +128,7 @@ def create_function_with_http_info(id, name, code, runtime, opts = {}) return_type = opts[:debug_return_type] || 'Function' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.create_function", @@ -208,7 +208,7 @@ def create_function_scheduler_with_http_info(id, function_id, create_function_sc return_type = opts[:debug_return_type] || 'FunctionScheduler' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.create_function_scheduler", @@ -286,7 +286,7 @@ def create_functions_batch_with_http_info(id, functions, opts = {}) return_type = opts[:debug_return_type] || 'BatchFunctionDeployResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.create_functions_batch", @@ -355,7 +355,7 @@ def delete_function_with_http_info(id, function_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.delete_function", @@ -428,7 +428,7 @@ def delete_function_scheduler_with_http_info(id, function_id, scheduler_id, opts return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.delete_function_scheduler", @@ -495,7 +495,7 @@ def get_function_with_http_info(id, function_id, opts = {}) return_type = opts[:debug_return_type] || 'Function' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.get_function", @@ -568,7 +568,7 @@ def get_function_scheduler_with_http_info(id, function_id, scheduler_id, opts = return_type = opts[:debug_return_type] || 'FunctionScheduler' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.get_function_scheduler", @@ -588,7 +588,7 @@ def get_function_scheduler_with_http_info(id, function_id, scheduler_id, opts = end # Invoke a function - # Invoke a serverless function. **With Service Key** (admin/background operations): - Use for background jobs, webhooks, cron, admin operations - Function receives payload only (no user context) - Database queries bypass RLS (admin access) **With Auth User Token** (user-facing): - Use for user-initiated actions - Function receives payload + `__volcano_auth` context: ```javascript { user_id: \"uuid\", email: \"user@example.com\", project_id: \"uuid\", role: \"authenticated\" or \"anonymous\" } ``` - Database queries enforce RLS (user-scoped data) **With Anon Key** (public function only): - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` - Function receives payload only (no `__volcano_auth`) **Transport and CORS:** - This operation is the authenticated direct RPC endpoint and always uses the POST `{payload: ...}` contract, including for functions whose DNS ingress is configured in HTTP mode. - The geo-routed DNS ingress is `https://{functionId}.functions./`. - RPC-mode DNS ingress accepts POST at `/`. HTTP-mode DNS ingress accepts GET, HEAD, POST, PUT, PATCH, and DELETE at `/` and nested paths. - Direct and RPC-mode CORS preflight advertises `POST, OPTIONS`. HTTP-mode DNS preflight advertises `GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`. - `http_auth_mode: none` applies only to public HTTP-mode DNS ingress; this direct operation always requires a Volcano credential. **Durable functions are not invocable here.** A durable function's id answers 404, whatever its visibility, because a synchronous call would run it with no execution record, no idempotency and no concurrency accounting. Start one with `POST /durable-functions/{functionId}/executions`. + # Invoke a function. **With Service Key** (admin/background operations): - Use for background jobs, webhooks, cron, admin operations - Function receives payload only (no user context) - Database queries bypass RLS (admin access) **With Auth User Token** (user-facing): - Use for user-initiated actions - Function receives payload + `__volcano_auth` context: ```javascript { user_id: \"uuid\", email: \"user@example.com\", project_id: \"uuid\", role: \"authenticated\" or \"anonymous\" } ``` - Database queries enforce RLS (user-scoped data) **With Anon Key** (public function only): - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` - Function receives payload only (no `__volcano_auth`) **Transport and CORS:** - This operation is the authenticated direct RPC endpoint and always uses the POST `{payload: ...}` contract, including for functions whose DNS ingress is configured in HTTP mode. - The geo-routed DNS ingress is the function's `invoke_url`. It is on a different domain from this API, so it cannot be derived from the API host. - RPC-mode DNS ingress accepts POST at `/`. HTTP-mode DNS ingress accepts GET, HEAD, POST, PUT, PATCH, and DELETE at `/` and nested paths. - Direct and RPC-mode CORS preflight advertises `POST, OPTIONS`. HTTP-mode DNS preflight advertises `GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`. - `http_auth_mode: none` applies only to public HTTP-mode DNS ingress; this direct operation always requires a Volcano credential. **Durable functions are not invocable here.** A durable function's id answers 404, whatever its visibility, because a synchronous call would run it with no execution record, no idempotency and no concurrency accounting. Start one with `POST /durable-functions/{functionId}/executions`. # @param function_id [String] Function ID # @param function_invocation_request [FunctionInvocationRequest] # @param [Hash] opts the optional parameters @@ -599,7 +599,7 @@ def invoke_function(function_id, function_invocation_request, opts = {}) end # Invoke a function - # Invoke a serverless function. **With Service Key** (admin/background operations): - Use for background jobs, webhooks, cron, admin operations - Function receives payload only (no user context) - Database queries bypass RLS (admin access) **With Auth User Token** (user-facing): - Use for user-initiated actions - Function receives payload + `__volcano_auth` context: ```javascript { user_id: \"uuid\", email: \"user@example.com\", project_id: \"uuid\", role: \"authenticated\" or \"anonymous\" } ``` - Database queries enforce RLS (user-scoped data) **With Anon Key** (public function only): - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` - Function receives payload only (no `__volcano_auth`) **Transport and CORS:** - This operation is the authenticated direct RPC endpoint and always uses the POST `{payload: ...}` contract, including for functions whose DNS ingress is configured in HTTP mode. - The geo-routed DNS ingress is `https://{functionId}.functions.<domain>/`. - RPC-mode DNS ingress accepts POST at `/`. HTTP-mode DNS ingress accepts GET, HEAD, POST, PUT, PATCH, and DELETE at `/` and nested paths. - Direct and RPC-mode CORS preflight advertises `POST, OPTIONS`. HTTP-mode DNS preflight advertises `GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`. - `http_auth_mode: none` applies only to public HTTP-mode DNS ingress; this direct operation always requires a Volcano credential. **Durable functions are not invocable here.** A durable function's id answers 404, whatever its visibility, because a synchronous call would run it with no execution record, no idempotency and no concurrency accounting. Start one with `POST /durable-functions/{functionId}/executions`. + # Invoke a function. **With Service Key** (admin/background operations): - Use for background jobs, webhooks, cron, admin operations - Function receives payload only (no user context) - Database queries bypass RLS (admin access) **With Auth User Token** (user-facing): - Use for user-initiated actions - Function receives payload + `__volcano_auth` context: ```javascript { user_id: \"uuid\", email: \"user@example.com\", project_id: \"uuid\", role: \"authenticated\" or \"anonymous\" } ``` - Database queries enforce RLS (user-scoped data) **With Anon Key** (public function only): - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` - Function receives payload only (no `__volcano_auth`) **Transport and CORS:** - This operation is the authenticated direct RPC endpoint and always uses the POST `{payload: ...}` contract, including for functions whose DNS ingress is configured in HTTP mode. - The geo-routed DNS ingress is the function's `invoke_url`. It is on a different domain from this API, so it cannot be derived from the API host. - RPC-mode DNS ingress accepts POST at `/`. HTTP-mode DNS ingress accepts GET, HEAD, POST, PUT, PATCH, and DELETE at `/` and nested paths. - Direct and RPC-mode CORS preflight advertises `POST, OPTIONS`. HTTP-mode DNS preflight advertises `GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`. - `http_auth_mode: none` applies only to public HTTP-mode DNS ingress; this direct operation always requires a Volcano credential. **Durable functions are not invocable here.** A durable function's id answers 404, whatever its visibility, because a synchronous call would run it with no execution record, no idempotency and no concurrency accounting. Start one with `POST /durable-functions/{functionId}/executions`. # @param function_id [String] Function ID # @param function_invocation_request [FunctionInvocationRequest] # @param [Hash] opts the optional parameters @@ -727,7 +727,7 @@ def list_function_deployments_with_http_info(id, function_id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedFunctionDeployments' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.list_function_deployments", @@ -804,7 +804,7 @@ def list_function_regions_with_http_info(opts = {}) end # List supported function runtimes - # Returns the public function runtime catalog used by CLI clients to select supported runtimes, language defaults, and local source packaging metadata for deployments. This is a public endpoint that doesn't require authentication. + # Returns the public function runtime catalog: every runtime a deploy accepts, its display label for runtime pickers, language defaults, durable capability, and local source packaging metadata for deployments. This is a public endpoint that doesn't require authentication. # @param [Hash] opts the optional parameters # @return [FunctionRuntimesResponse] def list_function_runtimes(opts = {}) @@ -813,7 +813,7 @@ def list_function_runtimes(opts = {}) end # List supported function runtimes - # Returns the public function runtime catalog used by CLI clients to select supported runtimes, language defaults, and local source packaging metadata for deployments. This is a public endpoint that doesn't require authentication. + # Returns the public function runtime catalog: every runtime a deploy accepts, its display label for runtime pickers, language defaults, durable capability, and local source packaging metadata for deployments. This is a public endpoint that doesn't require authentication. # @param [Hash] opts the optional parameters # @return [Array<(FunctionRuntimesResponse, Integer, Hash)>] FunctionRuntimesResponse data, response status code and response headers def list_function_runtimes_with_http_info(opts = {}) @@ -908,7 +908,7 @@ def list_function_schedulers_with_http_info(id, function_id, opts = {}) return_type = opts[:debug_return_type] || 'FunctionSchedulerListResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.list_function_schedulers", @@ -1009,7 +1009,7 @@ def list_functions_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedFunctions' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.list_functions", @@ -1110,7 +1110,7 @@ def list_project_schedulers_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'FunctionSchedulerListResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.list_project_schedulers", @@ -1130,7 +1130,7 @@ def list_project_schedulers_with_http_info(id, opts = {}) end # Resolve function name for invocation - # Resolves a DNS-safe function name to its function ID within the caller's project. SDKs use this endpoint internally to invoke by function name while routing by function ID. **With Service Key**: - Allowed **With Auth User Token**: - Allowed **With Anon Key**: - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` + # Resolves a DNS-safe function name to its function ID and invocation URL within the caller's project. SDKs use this endpoint internally to invoke by function name while routing by function ID. Invoke the returned `invoke_url` as-is. It does not share a domain with the API, so a host built from the API URL will not reach the function. When the deployment serves no public invocation domain, as in local development, `invoke_url` is omitted and callers invoke through `POST /functions/{functionId}/invoke`. **With Service Key**: - Allowed **With Auth User Token**: - Allowed **With Anon Key**: - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` # @param name [String] DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) # @param [Hash] opts the optional parameters # @return [ResolveFunctionResponse] @@ -1140,7 +1140,7 @@ def resolve_function_for_invocation(name, opts = {}) end # Resolve function name for invocation - # Resolves a DNS-safe function name to its function ID within the caller's project. SDKs use this endpoint internally to invoke by function name while routing by function ID. **With Service Key**: - Allowed **With Auth User Token**: - Allowed **With Anon Key**: - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` + # Resolves a DNS-safe function name to its function ID and invocation URL within the caller's project. SDKs use this endpoint internally to invoke by function name while routing by function ID. Invoke the returned `invoke_url` as-is. It does not share a domain with the API, so a host built from the API URL will not reach the function. When the deployment serves no public invocation domain, as in local development, `invoke_url` is omitted and callers invoke through `POST /functions/{functionId}/invoke`. **With Service Key**: - Allowed **With Auth User Token**: - Allowed **With Anon Key**: - Requires anon key permission: `functions.invoke` - Function must have `is_public: true` # @param name [String] DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) # @param [Hash] opts the optional parameters # @return [Array<(ResolveFunctionResponse, Integer, Hash)>] ResolveFunctionResponse data, response status code and response headers @@ -1261,7 +1261,7 @@ def update_function_with_http_info(id, function_id, update_function_request, opt return_type = opts[:debug_return_type] || 'Function' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.update_function", @@ -1345,7 +1345,7 @@ def update_function_scheduler_with_http_info(id, function_id, scheduler_id, upda return_type = opts[:debug_return_type] || 'FunctionScheduler' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"FunctionsApi.update_function_scheduler", diff --git a/lib/volcano/generated/lib/volcano-generated/api/git_connections_api.rb b/lib/volcano/generated/lib/volcano-generated/api/git_connections_api.rb index 96063c73..bf3c5fe8 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/git_connections_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/git_connections_api.rb @@ -63,7 +63,7 @@ def cancel_project_source_export_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.cancel_project_source_export", @@ -137,7 +137,7 @@ def connect_project_git_with_http_info(id, connect_project_git_request, opts = { return_type = opts[:debug_return_type] || 'ProjectGitConnection' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.connect_project_git", @@ -259,7 +259,7 @@ def disconnect_project_git_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.disconnect_project_git", @@ -333,7 +333,7 @@ def export_project_source_with_http_info(id, export_project_source_request, opts return_type = opts[:debug_return_type] || 'ProjectSourceExport' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.export_project_source", @@ -394,7 +394,7 @@ def get_project_git_connection_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectGitConnection' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.get_project_git_connection", @@ -455,7 +455,7 @@ def get_project_git_deploy_settings_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectGitDeploySettings' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.get_project_git_deploy_settings", @@ -518,7 +518,7 @@ def get_project_source_export_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectSourceExportState' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.get_project_source_export", @@ -849,7 +849,7 @@ def set_project_git_production_branch_with_http_info(id, set_project_git_product return_type = opts[:debug_return_type] || 'ProjectGitConnection' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.set_project_git_production_branch", @@ -873,6 +873,7 @@ def set_project_git_production_branch_with_http_info(id, set_project_git_product # @param [Hash] opts the optional parameters # @option opts [String] :provider Git provider to connect. Defaults to github. (default to 'github') # @option opts [String] :redirect URL to redirect the browser to after the provider callback completes. + # @option opts [String] :callback_url Same-origin browser callback used to relay provider parameters before completing the connection. # @return [GitConnectStartResponse] def start_git_connect(opts = {}) data, _status_code, _headers = start_git_connect_with_http_info(opts) @@ -884,6 +885,7 @@ def start_git_connect(opts = {}) # @param [Hash] opts the optional parameters # @option opts [String] :provider Git provider to connect. Defaults to github. (default to 'github') # @option opts [String] :redirect URL to redirect the browser to after the provider callback completes. + # @option opts [String] :callback_url Same-origin browser callback used to relay provider parameters before completing the connection. # @return [Array<(GitConnectStartResponse, Integer, Hash)>] GitConnectStartResponse data, response status code and response headers def start_git_connect_with_http_info(opts = {}) if @api_client.config.debugging @@ -893,6 +895,11 @@ def start_git_connect_with_http_info(opts = {}) if @api_client.config.client_side_validation && opts[:'provider'] && !allowable_values.include?(opts[:'provider']) fail ArgumentError, "invalid value for \"provider\", must be one of #{allowable_values}" end + pattern = Regexp.new(/^https:\/\/[^\/?#]+\/[^?#]*$|^http:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?\/[^?#]*$/) + if @api_client.config.client_side_validation && !opts[:'callback_url'].nil? && opts[:'callback_url'] !~ pattern + fail ArgumentError, "invalid value for 'opts[:\"callback_url\"]' when calling GitConnectionsApi.start_git_connect, must conform to the pattern #{pattern}." + end + # resource path local_var_path = '/user/git/connect' @@ -900,6 +907,7 @@ def start_git_connect_with_http_info(opts = {}) query_params = opts[:query_params] || {} query_params[:'provider'] = opts[:'provider'] if !opts[:'provider'].nil? query_params[:'redirect'] = opts[:'redirect'] if !opts[:'redirect'].nil? + query_params[:'callback_url'] = opts[:'callback_url'] if !opts[:'callback_url'].nil? # header parameters header_params = opts[:header_params] || {} @@ -990,7 +998,7 @@ def update_project_git_deploy_settings_with_http_info(id, update_project_git_dep return_type = opts[:debug_return_type] || 'ProjectGitDeploySettings' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"GitConnectionsApi.update_project_git_deploy_settings", diff --git a/lib/volcano/generated/lib/volcano-generated/api/logs_api.rb b/lib/volcano/generated/lib/volcano-generated/api/logs_api.rb index f00d30c4..60474d21 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/logs_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/logs_api.rb @@ -20,7 +20,7 @@ def initialize(api_client = ApiClient.default) @api_client = api_client end # Get project log activity - # Retrieve bucketed log counts for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to count deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database` from a HOBBY-plan project owner returns 403. The activity window is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older start times are clamped to that window. + # Retrieve bucketed log counts for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to count deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT feature; `resource.type=database` from a HOBBY project owner returns 403. The activity window is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older start times are clamped to that window. Buckets are aligned to UTC clock intervals and count events in the half-open window `[start_time, end_time)`. # @param id [String] Project ID # @param log_activity_request [LogActivityRequest] # @param [Hash] opts the optional parameters @@ -31,7 +31,7 @@ def get_project_log_activity(id, log_activity_request, opts = {}) end # Get project log activity - # Retrieve bucketed log counts for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to count deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database` from a HOBBY-plan project owner returns 403. The activity window is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older start times are clamped to that window. + # Retrieve bucketed log counts for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to count deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT feature; `resource.type=database` from a HOBBY project owner returns 403. The activity window is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older start times are clamped to that window. Buckets are aligned to UTC clock intervals and count events in the half-open window `[start_time, end_time)`. # @param id [String] Project ID # @param log_activity_request [LogActivityRequest] # @param [Hash] opts the optional parameters @@ -74,7 +74,7 @@ def get_project_log_activity_with_http_info(id, log_activity_request, opts = {}) return_type = opts[:debug_return_type] || 'LogActivityResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"LogsApi.get_project_log_activity", @@ -94,7 +94,7 @@ def get_project_log_activity_with_http_info(id, log_activity_request, opts = {}) end # Search project logs - # Search or filter logs for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to read deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT-plan feature; requests for `resource.type=database` from a HOBBY-plan project owner return 403. Log history (runtime and deployment) is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older time ranges are clamped to that window. + # Search or filter logs for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to read deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT feature; requests for `resource.type=database` from a HOBBY project owner return 403. Log history (runtime and deployment) is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older time ranges are clamped to that window. # @param id [String] Project ID # @param log_search_request [LogSearchRequest] # @param [Hash] opts the optional parameters @@ -105,7 +105,7 @@ def search_project_logs(id, log_search_request, opts = {}) end # Search project logs - # Search or filter logs for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to read deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT-plan feature; requests for `resource.type=database` from a HOBBY-plan project owner return 403. Log history (runtime and deployment) is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older time ranges are clamped to that window. + # Search or filter logs for one resource type in the project. Set `resource.type` to `function`, `frontend`, or `database`. Add `resource.ids` to filter to one or more resources, and add `resource.deployments.ids` to read deployment logs instead of runtime logs for functions and frontends. Deployment logs are not supported for databases. Database logs are a SUPERAGENT feature; requests for `resource.type=database` from a HOBBY project owner return 403. Log history (runtime and deployment) is limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older time ranges are clamped to that window. # @param id [String] Project ID # @param log_search_request [LogSearchRequest] # @param [Hash] opts the optional parameters @@ -148,7 +148,7 @@ def search_project_logs_with_http_info(id, log_search_request, opts = {}) return_type = opts[:debug_return_type] || 'LogSearchResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"LogsApi.search_project_logs", @@ -168,7 +168,7 @@ def search_project_logs_with_http_info(id, log_search_request, opts = {}) end # Stream project logs - # Live-tail project logs as Server-Sent Events. The request body uses the resource selector plus `q`, `start_time`, and `limit`, including runtime logs and function/frontend deployment logs selected with `resource.deployments`. Deployment logs are not supported for databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database` from a HOBBY-plan project owner returns 403. The `q` field uses the same syntax as search and activity requests. Do not send `cursor` or `end_time`; use `/logs/search` for range backfills. Explicit historical `start_time` values are limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days). Resume with `Last-Event-ID` or the `last_event_id` query parameter. The cursor is bound to the request body: the resource selector and every filter must match the original request when reconnecting, otherwise the request is rejected with `400`. This is a live tail, not a gap-free backfill. On connect or reconnect the server delivers at most `limit` of the most recent matching events from the cursor position and then follows new events; events older than that window are not replayed. Use `/logs/search` to backfill a time range. + # Live-tail project logs as Server-Sent Events. The request body uses the resource selector plus `q`, `start_time`, and `limit`, including runtime logs and function/frontend deployment logs selected with `resource.deployments`. Deployment logs are not supported for databases. Database logs are a SUPERAGENT feature; `resource.type=database` from a HOBBY project owner returns 403. The `q` field uses the same syntax as search and activity requests. Do not send `cursor` or `end_time`; use `/logs/search` for range backfills. Explicit historical `start_time` values are limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days). Resume with `Last-Event-ID` or the `last_event_id` query parameter. The cursor is bound to the request body: the resource selector and every filter must match the original request when reconnecting, otherwise the request is rejected with `400`. This is a live tail, not a gap-free backfill. On connect or reconnect the server delivers at most `limit` of the most recent matching events from the cursor position and then follows new events; events older than that window are not replayed. Use `/logs/search` to backfill a time range. # @param id [String] Project ID # @param log_stream_request [LogStreamRequest] # @param [Hash] opts the optional parameters @@ -181,7 +181,7 @@ def stream_project_logs(id, log_stream_request, opts = {}) end # Stream project logs - # Live-tail project logs as Server-Sent Events. The request body uses the resource selector plus `q`, `start_time`, and `limit`, including runtime logs and function/frontend deployment logs selected with `resource.deployments`. Deployment logs are not supported for databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database` from a HOBBY-plan project owner returns 403. The `q` field uses the same syntax as search and activity requests. Do not send `cursor` or `end_time`; use `/logs/search` for range backfills. Explicit historical `start_time` values are limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days). Resume with `Last-Event-ID` or the `last_event_id` query parameter. The cursor is bound to the request body: the resource selector and every filter must match the original request when reconnecting, otherwise the request is rejected with `400`. This is a live tail, not a gap-free backfill. On connect or reconnect the server delivers at most `limit` of the most recent matching events from the cursor position and then follows new events; events older than that window are not replayed. Use `/logs/search` to backfill a time range. + # Live-tail project logs as Server-Sent Events. The request body uses the resource selector plus `q`, `start_time`, and `limit`, including runtime logs and function/frontend deployment logs selected with `resource.deployments`. Deployment logs are not supported for databases. Database logs are a SUPERAGENT feature; `resource.type=database` from a HOBBY project owner returns 403. The `q` field uses the same syntax as search and activity requests. Do not send `cursor` or `end_time`; use `/logs/search` for range backfills. Explicit historical `start_time` values are limited to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days). Resume with `Last-Event-ID` or the `last_event_id` query parameter. The cursor is bound to the request body: the resource selector and every filter must match the original request when reconnecting, otherwise the request is rejected with `400`. This is a live tail, not a gap-free backfill. On connect or reconnect the server delivers at most `limit` of the most recent matching events from the cursor position and then follows new events; events older than that window are not replayed. Use `/logs/search` to backfill a time range. # @param id [String] Project ID # @param log_stream_request [LogStreamRequest] # @param [Hash] opts the optional parameters @@ -228,7 +228,7 @@ def stream_project_logs_with_http_info(id, log_stream_request, opts = {}) return_type = opts[:debug_return_type] || 'String' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"LogsApi.stream_project_logs", diff --git a/lib/volcano/generated/lib/volcano-generated/api/o_auth_configuration_api.rb b/lib/volcano/generated/lib/volcano-generated/api/o_auth_configuration_api.rb index 2f8dfb13..77f5edf0 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/o_auth_configuration_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/o_auth_configuration_api.rb @@ -74,7 +74,7 @@ def create_o_auth_config_with_http_info(id, create_o_auth_config_request, opts = return_type = opts[:debug_return_type] || 'OAuthConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"OAuthConfigurationApi.create_o_auth_config", @@ -147,7 +147,7 @@ def delete_o_auth_config_with_http_info(id, provider, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"OAuthConfigurationApi.delete_o_auth_config", @@ -222,7 +222,7 @@ def get_o_auth_config_with_http_info(id, provider, opts = {}) return_type = opts[:debug_return_type] || 'OAuthConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"OAuthConfigurationApi.get_o_auth_config", @@ -285,7 +285,7 @@ def list_available_o_auth_providers_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ListAvailableOAuthProviders200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"OAuthConfigurationApi.list_available_o_auth_providers", @@ -348,7 +348,7 @@ def list_o_auth_configs_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ListOAuthConfigs200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"OAuthConfigurationApi.list_o_auth_configs", @@ -430,7 +430,7 @@ def update_o_auth_config_with_http_info(id, provider, opts = {}) return_type = opts[:debug_return_type] || 'OAuthConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"OAuthConfigurationApi.update_o_auth_config", diff --git a/lib/volcano/generated/lib/volcano-generated/api/project_access_tokens_api.rb b/lib/volcano/generated/lib/volcano-generated/api/project_access_tokens_api.rb new file mode 100644 index 00000000..a0276cb4 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/api/project_access_tokens_api.rb @@ -0,0 +1,479 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'cgi' + +module Volcano::Generated + class ProjectAccessTokensApi + attr_accessor :api_client + + def initialize(api_client = ApiClient.default) + @api_client = api_client + end + # Create a project access token + # Creates a project access token and returns its secret. The secret is in this response and nowhere else. Only its hash is stored, so it cannot be retrieved, displayed, or recovered later — save it when you create it. The name must be unique within the project, so a retry cannot mint a second credential. It cannot recover the first one either. A retry that returns `409` with code `access_token_name_exists` means the original create committed and its secret is unrecoverable: list the project's tokens, revoke the one holding that name, and create it again. Requires a platform token. + # @param id [String] Project ID + # @param create_project_access_token_request [CreateProjectAccessTokenRequest] + # @param [Hash] opts the optional parameters + # @return [CreatedProjectAccessToken] + def create_project_access_token(id, create_project_access_token_request, opts = {}) + data, _status_code, _headers = create_project_access_token_with_http_info(id, create_project_access_token_request, opts) + data + end + + # Create a project access token + # Creates a project access token and returns its secret. The secret is in this response and nowhere else. Only its hash is stored, so it cannot be retrieved, displayed, or recovered later — save it when you create it. The name must be unique within the project, so a retry cannot mint a second credential. It cannot recover the first one either. A retry that returns `409` with code `access_token_name_exists` means the original create committed and its secret is unrecoverable: list the project's tokens, revoke the one holding that name, and create it again. Requires a platform token. + # @param id [String] Project ID + # @param create_project_access_token_request [CreateProjectAccessTokenRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(CreatedProjectAccessToken, Integer, Hash)>] CreatedProjectAccessToken data, response status code and response headers + def create_project_access_token_with_http_info(id, create_project_access_token_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: ProjectAccessTokensApi.create_project_access_token ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling ProjectAccessTokensApi.create_project_access_token" + end + # verify the required parameter 'create_project_access_token_request' is set + if @api_client.config.client_side_validation && create_project_access_token_request.nil? + fail ArgumentError, "Missing the required parameter 'create_project_access_token_request' when calling ProjectAccessTokensApi.create_project_access_token" + end + # resource path + local_var_path = '/projects/{id}/access-tokens'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(create_project_access_token_request) + + # return_type + return_type = opts[:debug_return_type] || 'CreatedProjectAccessToken' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken'] + + new_options = opts.merge( + :operation => :"ProjectAccessTokensApi.create_project_access_token", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: ProjectAccessTokensApi#create_project_access_token\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Get a project access token + # Returns one token's metadata. Never its secret, which is not stored in a recoverable form. Requires a platform token. + # @param id [String] Project ID + # @param token_id [String] Project access token ID + # @param [Hash] opts the optional parameters + # @return [ProjectAccessToken] + def get_project_access_token(id, token_id, opts = {}) + data, _status_code, _headers = get_project_access_token_with_http_info(id, token_id, opts) + data + end + + # Get a project access token + # Returns one token's metadata. Never its secret, which is not stored in a recoverable form. Requires a platform token. + # @param id [String] Project ID + # @param token_id [String] Project access token ID + # @param [Hash] opts the optional parameters + # @return [Array<(ProjectAccessToken, Integer, Hash)>] ProjectAccessToken data, response status code and response headers + def get_project_access_token_with_http_info(id, token_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: ProjectAccessTokensApi.get_project_access_token ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling ProjectAccessTokensApi.get_project_access_token" + end + # verify the required parameter 'token_id' is set + if @api_client.config.client_side_validation && token_id.nil? + fail ArgumentError, "Missing the required parameter 'token_id' when calling ProjectAccessTokensApi.get_project_access_token" + end + # resource path + local_var_path = '/projects/{id}/access-tokens/{tokenId}'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'tokenId' + '}', CGI.escape(token_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'ProjectAccessToken' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken'] + + new_options = opts.merge( + :operation => :"ProjectAccessTokensApi.get_project_access_token", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: ProjectAccessTokensApi#get_project_access_token\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Per-day request counts for one access token + # Returns a zero-filled daily series of request counts for a single token, oldest first, so the response always has exactly `days` entries. `days` defaults to 30 and is capped at 60, matching how long per-day counts are retained. A project access token may read only its own usage; asking for another token's returns `403`. A platform token may read any token in the project. + # @param id [String] Project ID + # @param token_id [String] Project access token ID + # @param [Hash] opts the optional parameters + # @option opts [Integer] :days Number of trailing days to return (1-60, default 30). (default to 30) + # @return [ProjectAccessTokenUsage] + def get_project_access_token_usage(id, token_id, opts = {}) + data, _status_code, _headers = get_project_access_token_usage_with_http_info(id, token_id, opts) + data + end + + # Per-day request counts for one access token + # Returns a zero-filled daily series of request counts for a single token, oldest first, so the response always has exactly `days` entries. `days` defaults to 30 and is capped at 60, matching how long per-day counts are retained. A project access token may read only its own usage; asking for another token's returns `403`. A platform token may read any token in the project. + # @param id [String] Project ID + # @param token_id [String] Project access token ID + # @param [Hash] opts the optional parameters + # @option opts [Integer] :days Number of trailing days to return (1-60, default 30). (default to 30) + # @return [Array<(ProjectAccessTokenUsage, Integer, Hash)>] ProjectAccessTokenUsage data, response status code and response headers + def get_project_access_token_usage_with_http_info(id, token_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: ProjectAccessTokensApi.get_project_access_token_usage ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling ProjectAccessTokensApi.get_project_access_token_usage" + end + # verify the required parameter 'token_id' is set + if @api_client.config.client_side_validation && token_id.nil? + fail ArgumentError, "Missing the required parameter 'token_id' when calling ProjectAccessTokensApi.get_project_access_token_usage" + end + if @api_client.config.client_side_validation && !opts[:'days'].nil? && opts[:'days'] > 60 + fail ArgumentError, 'invalid value for "opts[:"days"]" when calling ProjectAccessTokensApi.get_project_access_token_usage, must be smaller than or equal to 60.' + end + + if @api_client.config.client_side_validation && !opts[:'days'].nil? && opts[:'days'] < 1 + fail ArgumentError, 'invalid value for "opts[:"days"]" when calling ProjectAccessTokensApi.get_project_access_token_usage, must be greater than or equal to 1.' + end + + # resource path + local_var_path = '/projects/{id}/access-tokens/{tokenId}/usage'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'tokenId' + '}', CGI.escape(token_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + query_params[:'days'] = opts[:'days'] if !opts[:'days'].nil? + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'ProjectAccessTokenUsage' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] + + new_options = opts.merge( + :operation => :"ProjectAccessTokensApi.get_project_access_token_usage", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: ProjectAccessTokensApi#get_project_access_token_usage\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # List a project's access tokens + # Lists the project's access tokens, newest first. Secrets are never returned: only a hash is stored, so a token's value exists solely in the response to the create call. Only tokens that can still authenticate are returned by default, so revoked and expired ones are hidden. Pass `include_revoked=true` to see them, which is how you find out what a key did before it stopped working. Requires a platform token. A project access token cannot manage project access tokens, so a leaked credential cannot enumerate or replace itself. + # @param id [String] Project ID + # @param [Hash] opts the optional parameters + # @option opts [Integer] :page Page number (1-indexed) for offset pagination. Declares no schema default so the request validator does not inject one: handlers that omit `page` see it unset (nil) and default to 1 in code, while cursor-first endpoints (e.g. the project deployments feed) can detect its absence to stay in keyset/search mode. Supplying `page` selects offset pagination. + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :search Case-insensitive substring match on the resource `name`. See the endpoint description for supported pagination modes. + # @option opts [Boolean] :include_revoked Include tokens that can no longer authenticate — both revoked and expired ones. (default to false) + # @return [PaginatedProjectAccessTokens] + def list_project_access_tokens(id, opts = {}) + data, _status_code, _headers = list_project_access_tokens_with_http_info(id, opts) + data + end + + # List a project's access tokens + # Lists the project's access tokens, newest first. Secrets are never returned: only a hash is stored, so a token's value exists solely in the response to the create call. Only tokens that can still authenticate are returned by default, so revoked and expired ones are hidden. Pass `include_revoked=true` to see them, which is how you find out what a key did before it stopped working. Requires a platform token. A project access token cannot manage project access tokens, so a leaked credential cannot enumerate or replace itself. + # @param id [String] Project ID + # @param [Hash] opts the optional parameters + # @option opts [Integer] :page Page number (1-indexed) for offset pagination. Declares no schema default so the request validator does not inject one: handlers that omit `page` see it unset (nil) and default to 1 in code, while cursor-first endpoints (e.g. the project deployments feed) can detect its absence to stay in keyset/search mode. Supplying `page` selects offset pagination. + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :search Case-insensitive substring match on the resource `name`. See the endpoint description for supported pagination modes. + # @option opts [Boolean] :include_revoked Include tokens that can no longer authenticate — both revoked and expired ones. (default to false) + # @return [Array<(PaginatedProjectAccessTokens, Integer, Hash)>] PaginatedProjectAccessTokens data, response status code and response headers + def list_project_access_tokens_with_http_info(id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: ProjectAccessTokensApi.list_project_access_tokens ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling ProjectAccessTokensApi.list_project_access_tokens" + end + if @api_client.config.client_side_validation && !opts[:'page'].nil? && opts[:'page'] < 1 + fail ArgumentError, 'invalid value for "opts[:"page"]" when calling ProjectAccessTokensApi.list_project_access_tokens, must be greater than or equal to 1.' + end + + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] > 100 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling ProjectAccessTokensApi.list_project_access_tokens, must be smaller than or equal to 100.' + end + + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] < 1 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling ProjectAccessTokensApi.list_project_access_tokens, must be greater than or equal to 1.' + end + + if @api_client.config.client_side_validation && !opts[:'search'].nil? && opts[:'search'].to_s.length > 256 + fail ArgumentError, 'invalid value for "opts[:"search"]" when calling ProjectAccessTokensApi.list_project_access_tokens, the character length must be smaller than or equal to 256.' + end + + # resource path + local_var_path = '/projects/{id}/access-tokens'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + query_params[:'page'] = opts[:'page'] if !opts[:'page'].nil? + query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil? + query_params[:'search'] = opts[:'search'] if !opts[:'search'].nil? + query_params[:'include_revoked'] = opts[:'include_revoked'] if !opts[:'include_revoked'].nil? + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'PaginatedProjectAccessTokens' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken'] + + new_options = opts.merge( + :operation => :"ProjectAccessTokensApi.list_project_access_tokens", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: ProjectAccessTokensApi#list_project_access_tokens\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Per-day request counts for every access token in a project + # Returns a zero-filled daily series of request counts for each of the project's access tokens, oldest first. Every day in the window is present, so a gap reads as zero rather than missing. Revoked tokens are included, because the traffic they made before revocation is usually the reason you are looking. `days` defaults to 30 and is capped at 60, which is also how long per-day counts are retained — a longer window cannot be answered. A platform token sees every token in the project. A project access token sees only its own row, so it can watch its own traffic without being able to enumerate the project's other credentials by name. + # @param id [String] Project ID + # @param [Hash] opts the optional parameters + # @option opts [Integer] :days Number of trailing days to return (1-60, default 30). (default to 30) + # @return [Array] + def list_project_access_tokens_usage(id, opts = {}) + data, _status_code, _headers = list_project_access_tokens_usage_with_http_info(id, opts) + data + end + + # Per-day request counts for every access token in a project + # Returns a zero-filled daily series of request counts for each of the project's access tokens, oldest first. Every day in the window is present, so a gap reads as zero rather than missing. Revoked tokens are included, because the traffic they made before revocation is usually the reason you are looking. `days` defaults to 30 and is capped at 60, which is also how long per-day counts are retained — a longer window cannot be answered. A platform token sees every token in the project. A project access token sees only its own row, so it can watch its own traffic without being able to enumerate the project's other credentials by name. + # @param id [String] Project ID + # @param [Hash] opts the optional parameters + # @option opts [Integer] :days Number of trailing days to return (1-60, default 30). (default to 30) + # @return [Array<(Array, Integer, Hash)>] Array data, response status code and response headers + def list_project_access_tokens_usage_with_http_info(id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: ProjectAccessTokensApi.list_project_access_tokens_usage ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling ProjectAccessTokensApi.list_project_access_tokens_usage" + end + if @api_client.config.client_side_validation && !opts[:'days'].nil? && opts[:'days'] > 60 + fail ArgumentError, 'invalid value for "opts[:"days"]" when calling ProjectAccessTokensApi.list_project_access_tokens_usage, must be smaller than or equal to 60.' + end + + if @api_client.config.client_side_validation && !opts[:'days'].nil? && opts[:'days'] < 1 + fail ArgumentError, 'invalid value for "opts[:"days"]" when calling ProjectAccessTokensApi.list_project_access_tokens_usage, must be greater than or equal to 1.' + end + + # resource path + local_var_path = '/projects/{id}/access-tokens/usage'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + query_params[:'days'] = opts[:'days'] if !opts[:'days'].nil? + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'Array' + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] + + new_options = opts.merge( + :operation => :"ProjectAccessTokensApi.list_project_access_tokens_usage", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: ProjectAccessTokensApi#list_project_access_tokens_usage\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Revoke a project access token + # Revokes the token. It stops authenticating immediately in the region handling this call and within seconds across Volcano's other regions. The record is kept rather than deleted, so the token's name, prefix, last use, and request history stay available — which is what you need if you are revoking because a secret leaked. Revoking an already-revoked token succeeds. Revoking does not undo anything the token already did. Treat whatever it could reach as exposed and rotate accordingly. Requires a platform token. + # @param id [String] Project ID + # @param token_id [String] Project access token ID + # @param [Hash] opts the optional parameters + # @return [nil] + def revoke_project_access_token(id, token_id, opts = {}) + revoke_project_access_token_with_http_info(id, token_id, opts) + nil + end + + # Revoke a project access token + # Revokes the token. It stops authenticating immediately in the region handling this call and within seconds across Volcano's other regions. The record is kept rather than deleted, so the token's name, prefix, last use, and request history stay available — which is what you need if you are revoking because a secret leaked. Revoking an already-revoked token succeeds. Revoking does not undo anything the token already did. Treat whatever it could reach as exposed and rotate accordingly. Requires a platform token. + # @param id [String] Project ID + # @param token_id [String] Project access token ID + # @param [Hash] opts the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def revoke_project_access_token_with_http_info(id, token_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: ProjectAccessTokensApi.revoke_project_access_token ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling ProjectAccessTokensApi.revoke_project_access_token" + end + # verify the required parameter 'token_id' is set + if @api_client.config.client_side_validation && token_id.nil? + fail ArgumentError, "Missing the required parameter 'token_id' when calling ProjectAccessTokensApi.revoke_project_access_token" + end + # resource path + local_var_path = '/projects/{id}/access-tokens/{tokenId}'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'tokenId' + '}', CGI.escape(token_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken'] + + new_options = opts.merge( + :operation => :"ProjectAccessTokensApi.revoke_project_access_token", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: ProjectAccessTokensApi#revoke_project_access_token\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + end +end diff --git a/lib/volcano/generated/lib/volcano-generated/api/project_imports_api.rb b/lib/volcano/generated/lib/volcano-generated/api/project_imports_api.rb index 4311c7c7..04b92270 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/project_imports_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/project_imports_api.rb @@ -439,6 +439,7 @@ def preflight_project_import_with_http_info(provider, project_import_preflight_r # @param [Hash] opts the optional parameters # @option opts [ImportProvider] :provider Import provider to connect. Defaults to Vercel. (default to 'vercel') # @option opts [String] :redirect Validated application URL used after the provider callback. + # @option opts [String] :callback_url Same-origin browser callback used to relay provider parameters before completing the connection. # @return [ImportConnectStartResponse] def start_import_connect(opts = {}) data, _status_code, _headers = start_import_connect_with_http_info(opts) @@ -450,6 +451,7 @@ def start_import_connect(opts = {}) # @param [Hash] opts the optional parameters # @option opts [ImportProvider] :provider Import provider to connect. Defaults to Vercel. (default to 'vercel') # @option opts [String] :redirect Validated application URL used after the provider callback. + # @option opts [String] :callback_url Same-origin browser callback used to relay provider parameters before completing the connection. # @return [Array<(ImportConnectStartResponse, Integer, Hash)>] ImportConnectStartResponse data, response status code and response headers def start_import_connect_with_http_info(opts = {}) if @api_client.config.debugging @@ -460,6 +462,11 @@ def start_import_connect_with_http_info(opts = {}) fail ArgumentError, "invalid value for 'opts[:\"redirect\"]' when calling ProjectImportsApi.start_import_connect, must conform to the pattern #{pattern}." end + pattern = Regexp.new(/^https:\/\/[^\/?#]+\/[^?#]*$|^http:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?\/[^?#]*$/) + if @api_client.config.client_side_validation && !opts[:'callback_url'].nil? && opts[:'callback_url'] !~ pattern + fail ArgumentError, "invalid value for 'opts[:\"callback_url\"]' when calling ProjectImportsApi.start_import_connect, must conform to the pattern #{pattern}." + end + # resource path local_var_path = '/user/imports/connect' @@ -467,6 +474,7 @@ def start_import_connect_with_http_info(opts = {}) query_params = opts[:query_params] || {} query_params[:'provider'] = opts[:'provider'] if !opts[:'provider'].nil? query_params[:'redirect'] = opts[:'redirect'] if !opts[:'redirect'].nil? + query_params[:'callback_url'] = opts[:'callback_url'] if !opts[:'callback_url'].nil? # header parameters header_params = opts[:header_params] || {} diff --git a/lib/volcano/generated/lib/volcano-generated/api/projects_api.rb b/lib/volcano/generated/lib/volcano-generated/api/projects_api.rb index 31a61717..66d6c7f0 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/projects_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/projects_api.rb @@ -77,7 +77,7 @@ def apply_project_config_with_http_info(id, project_config, opts = {}) return_type = opts[:debug_return_type] || 'ProjectConfigApplyResult' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.apply_project_config", @@ -140,7 +140,7 @@ def cancel_project_source_export_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.cancel_project_source_export", @@ -214,7 +214,7 @@ def connect_project_git_with_http_info(id, connect_project_git_request, opts = { return_type = opts[:debug_return_type] || 'ProjectGitConnection' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.connect_project_git", @@ -345,7 +345,7 @@ def delete_project_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.delete_project", @@ -408,7 +408,7 @@ def delete_project_logo_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'Project' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.delete_project_logo", @@ -469,7 +469,7 @@ def disconnect_project_git_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.disconnect_project_git", @@ -543,7 +543,7 @@ def export_project_source_with_http_info(id, export_project_source_request, opts return_type = opts[:debug_return_type] || 'ProjectSourceExport' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.export_project_source", @@ -604,7 +604,7 @@ def get_project_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'Project' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.get_project", @@ -624,7 +624,7 @@ def get_project_with_http_info(id, opts = {}) end # Export project configuration - # Exports the project's current user-facing configuration as a declarative manifest. Returns JSON by default. Request the canonical volcano-config.yaml rendering with `Accept: application/yaml` or `?format=yaml`; the YAML is returned verbatim as the raw response body (`Content-Type: application/yaml`) and is meant to be saved as-is. Variable values and write-only secrets (SMTP password, OAuth client secrets, TLS material) are omitted from the export; shared_variables contains names only; the YAML rendering adds a header comment describing how to set them via CLI environment interpolation. + # Exports the project's current user-facing configuration as a declarative manifest. Returns JSON by default. Request the canonical volcano-config.yaml rendering with `Accept: application/yaml` or `?format=yaml`; the YAML is returned verbatim as the raw response body (`Content-Type: application/yaml`) and is meant to be saved as-is. Variable values and write-only secrets (SMTP password, OAuth client secrets, TLS material) are omitted from the export; shared_variables and frontend_shared_variables contain names only; the YAML rendering adds a header comment describing how to set them via CLI environment interpolation. # @param id [String] Project ID # @param [Hash] opts the optional parameters # @option opts [String] :format Response format override. Takes precedence over the Accept header. @@ -635,7 +635,7 @@ def get_project_config(id, opts = {}) end # Export project configuration - # Exports the project's current user-facing configuration as a declarative manifest. Returns JSON by default. Request the canonical volcano-config.yaml rendering with `Accept: application/yaml` or `?format=yaml`; the YAML is returned verbatim as the raw response body (`Content-Type: application/yaml`) and is meant to be saved as-is. Variable values and write-only secrets (SMTP password, OAuth client secrets, TLS material) are omitted from the export; shared_variables contains names only; the YAML rendering adds a header comment describing how to set them via CLI environment interpolation. + # Exports the project's current user-facing configuration as a declarative manifest. Returns JSON by default. Request the canonical volcano-config.yaml rendering with `Accept: application/yaml` or `?format=yaml`; the YAML is returned verbatim as the raw response body (`Content-Type: application/yaml`) and is meant to be saved as-is. Variable values and write-only secrets (SMTP password, OAuth client secrets, TLS material) are omitted from the export; shared_variables and frontend_shared_variables contain names only; the YAML rendering adds a header comment describing how to set them via CLI environment interpolation. # @param id [String] Project ID # @param [Hash] opts the optional parameters # @option opts [String] :format Response format override. Takes precedence over the Accept header. @@ -674,7 +674,7 @@ def get_project_config_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.get_project_config", @@ -735,7 +735,7 @@ def get_project_git_connection_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectGitConnection' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.get_project_git_connection", @@ -796,7 +796,7 @@ def get_project_git_deploy_settings_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectGitDeploySettings' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.get_project_git_deploy_settings", @@ -859,7 +859,7 @@ def get_project_health_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectHealthResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.get_project_health", @@ -985,7 +985,7 @@ def get_project_source_export_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectSourceExportState' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.get_project_source_export", @@ -1048,7 +1048,7 @@ def get_project_usage_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ProjectUsageResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.get_project_usage", @@ -1288,7 +1288,7 @@ def list_project_deployments_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedProjectDeployments' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.list_project_deployments", @@ -1464,7 +1464,7 @@ def query_project_metrics_with_http_info(id, project_metrics_query_request, opts return_type = opts[:debug_return_type] || 'ProjectMetricsQueryResponse' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.query_project_metrics", @@ -1483,6 +1483,80 @@ def query_project_metrics_with_http_info(id, project_metrics_query_request, opts return data, status_code, headers end + # Replace frontend shared variable names + # Atomically replaces the complete shared frontend-variable list without changing values. Names must already exist. Validates final affected frontend environments before membership or propagation side effects. An empty list clears membership. Omitted names remain stored outside the frontend shared list. + # @param id [String] Project ID + # @param replace_frontend_shared_variables_request [ReplaceFrontendSharedVariablesRequest] + # @param [Hash] opts the optional parameters + # @return [nil] + def replace_frontend_shared_variables(id, replace_frontend_shared_variables_request, opts = {}) + replace_frontend_shared_variables_with_http_info(id, replace_frontend_shared_variables_request, opts) + nil + end + + # Replace frontend shared variable names + # Atomically replaces the complete shared frontend-variable list without changing values. Names must already exist. Validates final affected frontend environments before membership or propagation side effects. An empty list clears membership. Omitted names remain stored outside the frontend shared list. + # @param id [String] Project ID + # @param replace_frontend_shared_variables_request [ReplaceFrontendSharedVariablesRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def replace_frontend_shared_variables_with_http_info(id, replace_frontend_shared_variables_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: ProjectsApi.replace_frontend_shared_variables ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling ProjectsApi.replace_frontend_shared_variables" + end + # verify the required parameter 'replace_frontend_shared_variables_request' is set + if @api_client.config.client_side_validation && replace_frontend_shared_variables_request.nil? + fail ArgumentError, "Missing the required parameter 'replace_frontend_shared_variables_request' when calling ProjectsApi.replace_frontend_shared_variables" + end + # resource path + local_var_path = '/projects/{id}/frontend-shared-variables'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(replace_frontend_shared_variables_request) + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || ['UserToken'] + + new_options = opts.merge( + :operation => :"ProjectsApi.replace_frontend_shared_variables", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:PUT, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: ProjectsApi#replace_frontend_shared_variables\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + # Replace shared variable names # Atomically replaces the complete shared function-variable list without changing values. Names must already exist. Validates final affected function environments before membership or propagation side effects. An empty list clears membership. Omitted names remain stored as non-shared variables. # @param id [String] Project ID @@ -1538,7 +1612,7 @@ def replace_shared_variables_with_http_info(id, replace_shared_variables_request return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.replace_shared_variables", @@ -1612,7 +1686,7 @@ def set_project_git_production_branch_with_http_info(id, set_project_git_product return_type = opts[:debug_return_type] || 'ProjectGitConnection' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.set_project_git_production_branch", @@ -1693,7 +1767,7 @@ def summarize_project_deployments_with_http_info(id, resource_type, opts = {}) return_type = opts[:debug_return_type] || 'ProjectDeploymentSummary' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.summarize_project_deployments", @@ -1765,7 +1839,7 @@ def update_project_with_http_info(id, update_project_request, opts = {}) return_type = opts[:debug_return_type] || 'Project' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.update_project", @@ -1839,7 +1913,7 @@ def update_project_git_deploy_settings_with_http_info(id, update_project_git_dep return_type = opts[:debug_return_type] || 'ProjectGitDeploySettings' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.update_project_git_deploy_settings", @@ -1914,7 +1988,7 @@ def upload_project_logo_with_http_info(id, logo, opts = {}) return_type = opts[:debug_return_type] || 'Project' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ProjectsApi.upload_project_logo", diff --git a/lib/volcano/generated/lib/volcano-generated/api/realtime_api.rb b/lib/volcano/generated/lib/volcano-generated/api/realtime_api.rb index dd7a821a..4d7cf802 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/realtime_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/realtime_api.rb @@ -63,7 +63,7 @@ def get_realtime_config_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'RealtimeConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"RealtimeApi.get_realtime_config", @@ -126,7 +126,7 @@ def get_realtime_stats_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'RealtimeStats' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"RealtimeApi.get_realtime_stats", @@ -200,7 +200,7 @@ def update_realtime_config_with_http_info(id, update_realtime_config_request, op return_type = opts[:debug_return_type] || 'RealtimeConfig' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"RealtimeApi.update_realtime_config", diff --git a/lib/volcano/generated/lib/volcano-generated/api/sandboxes_api.rb b/lib/volcano/generated/lib/volcano-generated/api/sandboxes_api.rb new file mode 100644 index 00000000..3e524f53 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/api/sandboxes_api.rb @@ -0,0 +1,1433 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'cgi' + +module Volcano::Generated + class SandboxesApi + attr_accessor :api_client + + def initialize(api_client = ApiClient.default) + @api_client = api_client + end + # Create a sandbox template from a verified preset + # @param id [String] + # @param idempotency_key [String] + # @param create_sandbox_template_request [CreateSandboxTemplateRequest] + # @param [Hash] opts the optional parameters + # @return [SandboxTemplate] + def create_sandbox(id, idempotency_key, create_sandbox_template_request, opts = {}) + data, _status_code, _headers = create_sandbox_with_http_info(id, idempotency_key, create_sandbox_template_request, opts) + data + end + + # Create a sandbox template from a verified preset + # @param id [String] + # @param idempotency_key [String] + # @param create_sandbox_template_request [CreateSandboxTemplateRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxTemplate, Integer, Hash)>] SandboxTemplate data, response status code and response headers + def create_sandbox_with_http_info(id, idempotency_key, create_sandbox_template_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.create_sandbox ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.create_sandbox" + end + # verify the required parameter 'idempotency_key' is set + if @api_client.config.client_side_validation && idempotency_key.nil? + fail ArgumentError, "Missing the required parameter 'idempotency_key' when calling SandboxesApi.create_sandbox" + end + # verify the required parameter 'create_sandbox_template_request' is set + if @api_client.config.client_side_validation && create_sandbox_template_request.nil? + fail ArgumentError, "Missing the required parameter 'create_sandbox_template_request' when calling SandboxesApi.create_sandbox" + end + # resource path + local_var_path = '/projects/{id}/sandboxes'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + header_params[:'Idempotency-Key'] = idempotency_key + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(create_sandbox_template_request) + + # return_type + return_type = opts[:debug_return_type] || 'SandboxTemplate' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.create_sandbox", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#create_sandbox\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Start a sandbox session + # @param id [String] + # @param idempotency_key [String] + # @param create_sandbox_session_request [CreateSandboxSessionRequest] + # @param [Hash] opts the optional parameters + # @return [SandboxSession] + def create_sandbox_session(id, idempotency_key, create_sandbox_session_request, opts = {}) + data, _status_code, _headers = create_sandbox_session_with_http_info(id, idempotency_key, create_sandbox_session_request, opts) + data + end + + # Start a sandbox session + # @param id [String] + # @param idempotency_key [String] + # @param create_sandbox_session_request [CreateSandboxSessionRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxSession, Integer, Hash)>] SandboxSession data, response status code and response headers + def create_sandbox_session_with_http_info(id, idempotency_key, create_sandbox_session_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.create_sandbox_session ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.create_sandbox_session" + end + # verify the required parameter 'idempotency_key' is set + if @api_client.config.client_side_validation && idempotency_key.nil? + fail ArgumentError, "Missing the required parameter 'idempotency_key' when calling SandboxesApi.create_sandbox_session" + end + # resource path + local_var_path = '/projects/{id}/sandbox-sessions'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + header_params[:'Idempotency-Key'] = idempotency_key + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(create_sandbox_session_request) + + # return_type + return_type = opts[:debug_return_type] || 'SandboxSession' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.create_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#create_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Issue a short-lived port-scoped access credential + # @param session_id [String] + # @param sandbox_access_request [SandboxAccessRequest] + # @param [Hash] opts the optional parameters + # @return [SandboxAccess] + def create_sandbox_session_access(session_id, sandbox_access_request, opts = {}) + data, _status_code, _headers = create_sandbox_session_access_with_http_info(session_id, sandbox_access_request, opts) + data + end + + # Issue a short-lived port-scoped access credential + # @param session_id [String] + # @param sandbox_access_request [SandboxAccessRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxAccess, Integer, Hash)>] SandboxAccess data, response status code and response headers + def create_sandbox_session_access_with_http_info(session_id, sandbox_access_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.create_sandbox_session_access ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.create_sandbox_session_access" + end + # verify the required parameter 'sandbox_access_request' is set + if @api_client.config.client_side_validation && sandbox_access_request.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_access_request' when calling SandboxesApi.create_sandbox_session_access" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/access'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(sandbox_access_request) + + # return_type + return_type = opts[:debug_return_type] || 'SandboxAccess' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'AuthUserAccessToken', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.create_sandbox_session_access", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#create_sandbox_session_access\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Retire a template and terminate its sessions + # @param id [String] + # @param sandbox_id [String] + # @param [Hash] opts the optional parameters + # @return [nil] + def delete_sandbox(id, sandbox_id, opts = {}) + delete_sandbox_with_http_info(id, sandbox_id, opts) + nil + end + + # Retire a template and terminate its sessions + # @param id [String] + # @param sandbox_id [String] + # @param [Hash] opts the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def delete_sandbox_with_http_info(id, sandbox_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.delete_sandbox ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.delete_sandbox" + end + # verify the required parameter 'sandbox_id' is set + if @api_client.config.client_side_validation && sandbox_id.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_id' when calling SandboxesApi.delete_sandbox" + end + # resource path + local_var_path = '/projects/{id}/sandboxes/{sandboxId}'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'sandboxId' + '}', CGI.escape(sandbox_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.delete_sandbox", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#delete_sandbox\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Execute once and return after confirmed termination + # @param id [String] + # @param idempotency_key [String] + # @param sandbox_execution_request [SandboxExecutionRequest] + # @param [Hash] opts the optional parameters + # @return [SandboxExecutionResult] + def execute_sandbox(id, idempotency_key, sandbox_execution_request, opts = {}) + data, _status_code, _headers = execute_sandbox_with_http_info(id, idempotency_key, sandbox_execution_request, opts) + data + end + + # Execute once and return after confirmed termination + # @param id [String] + # @param idempotency_key [String] + # @param sandbox_execution_request [SandboxExecutionRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxExecutionResult, Integer, Hash)>] SandboxExecutionResult data, response status code and response headers + def execute_sandbox_with_http_info(id, idempotency_key, sandbox_execution_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.execute_sandbox ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.execute_sandbox" + end + # verify the required parameter 'idempotency_key' is set + if @api_client.config.client_side_validation && idempotency_key.nil? + fail ArgumentError, "Missing the required parameter 'idempotency_key' when calling SandboxesApi.execute_sandbox" + end + # resource path + local_var_path = '/projects/{id}/sandbox-executions'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + header_params[:'Idempotency-Key'] = idempotency_key + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(sandbox_execution_request) + + # return_type + return_type = opts[:debug_return_type] || 'SandboxExecutionResult' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.execute_sandbox", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#execute_sandbox\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Execute a command within a session + # @param session_id [String] + # @param idempotency_key [String] + # @param sandbox_command_request [SandboxCommandRequest] + # @param [Hash] opts the optional parameters + # @return [SandboxCommandResult] + def execute_sandbox_session(session_id, idempotency_key, sandbox_command_request, opts = {}) + data, _status_code, _headers = execute_sandbox_session_with_http_info(session_id, idempotency_key, sandbox_command_request, opts) + data + end + + # Execute a command within a session + # @param session_id [String] + # @param idempotency_key [String] + # @param sandbox_command_request [SandboxCommandRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxCommandResult, Integer, Hash)>] SandboxCommandResult data, response status code and response headers + def execute_sandbox_session_with_http_info(session_id, idempotency_key, sandbox_command_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.execute_sandbox_session ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.execute_sandbox_session" + end + # verify the required parameter 'idempotency_key' is set + if @api_client.config.client_side_validation && idempotency_key.nil? + fail ArgumentError, "Missing the required parameter 'idempotency_key' when calling SandboxesApi.execute_sandbox_session" + end + # verify the required parameter 'sandbox_command_request' is set + if @api_client.config.client_side_validation && sandbox_command_request.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_command_request' when calling SandboxesApi.execute_sandbox_session" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/exec'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + header_params[:'Idempotency-Key'] = idempotency_key + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(sandbox_command_request) + + # return_type + return_type = opts[:debug_return_type] || 'SandboxCommandResult' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'AuthUserAccessToken', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.execute_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#execute_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Get a sandbox template + # @param id [String] + # @param sandbox_id [String] + # @param [Hash] opts the optional parameters + # @return [SandboxTemplate] + def get_sandbox(id, sandbox_id, opts = {}) + data, _status_code, _headers = get_sandbox_with_http_info(id, sandbox_id, opts) + data + end + + # Get a sandbox template + # @param id [String] + # @param sandbox_id [String] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxTemplate, Integer, Hash)>] SandboxTemplate data, response status code and response headers + def get_sandbox_with_http_info(id, sandbox_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.get_sandbox ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.get_sandbox" + end + # verify the required parameter 'sandbox_id' is set + if @api_client.config.client_side_validation && sandbox_id.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_id' when calling SandboxesApi.get_sandbox" + end + # resource path + local_var_path = '/projects/{id}/sandboxes/{sandboxId}'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'sandboxId' + '}', CGI.escape(sandbox_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxTemplate' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.get_sandbox", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#get_sandbox\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Get a sandbox session + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [SandboxSession] + def get_sandbox_session(session_id, opts = {}) + data, _status_code, _headers = get_sandbox_session_with_http_info(session_id, opts) + data + end + + # Get a sandbox session + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxSession, Integer, Hash)>] SandboxSession data, response status code and response headers + def get_sandbox_session_with_http_info(session_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.get_sandbox_session ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.get_sandbox_session" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxSession' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'AuthUserAccessToken', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.get_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#get_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Authorize an authenticated project user for this session + # @param session_id [String] + # @param subject_id [String] + # @param sandbox_subject_grant_request [SandboxSubjectGrantRequest] + # @param [Hash] opts the optional parameters + # @return [nil] + def grant_sandbox_session(session_id, subject_id, sandbox_subject_grant_request, opts = {}) + grant_sandbox_session_with_http_info(session_id, subject_id, sandbox_subject_grant_request, opts) + nil + end + + # Authorize an authenticated project user for this session + # @param session_id [String] + # @param subject_id [String] + # @param sandbox_subject_grant_request [SandboxSubjectGrantRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def grant_sandbox_session_with_http_info(session_id, subject_id, sandbox_subject_grant_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.grant_sandbox_session ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.grant_sandbox_session" + end + # verify the required parameter 'subject_id' is set + if @api_client.config.client_side_validation && subject_id.nil? + fail ArgumentError, "Missing the required parameter 'subject_id' when calling SandboxesApi.grant_sandbox_session" + end + # verify the required parameter 'sandbox_subject_grant_request' is set + if @api_client.config.client_side_validation && sandbox_subject_grant_request.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_subject_grant_request' when calling SandboxesApi.grant_sandbox_session" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/grants/{subjectId}'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)).sub('{' + 'subjectId' + '}', CGI.escape(subject_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(sandbox_subject_grant_request) + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.grant_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:PUT, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#grant_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # List sandbox deployment history + # @param id [String] + # @param sandbox_id [String] + # @param [Hash] opts the optional parameters + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :cursor Opaque keyset pagination cursor from a previous response's `next_cursor` — pages forward. Mutually exclusive with `page` and `ending_before`; combining them returns 400. When supplied, the request's `search` and `limit` must match the values bound to the cursor or the request returns 400. + # @return [SandboxDeploymentPage] + def list_sandbox_deployments(id, sandbox_id, opts = {}) + data, _status_code, _headers = list_sandbox_deployments_with_http_info(id, sandbox_id, opts) + data + end + + # List sandbox deployment history + # @param id [String] + # @param sandbox_id [String] + # @param [Hash] opts the optional parameters + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :cursor Opaque keyset pagination cursor from a previous response's `next_cursor` — pages forward. Mutually exclusive with `page` and `ending_before`; combining them returns 400. When supplied, the request's `search` and `limit` must match the values bound to the cursor or the request returns 400. + # @return [Array<(SandboxDeploymentPage, Integer, Hash)>] SandboxDeploymentPage data, response status code and response headers + def list_sandbox_deployments_with_http_info(id, sandbox_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.list_sandbox_deployments ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.list_sandbox_deployments" + end + # verify the required parameter 'sandbox_id' is set + if @api_client.config.client_side_validation && sandbox_id.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_id' when calling SandboxesApi.list_sandbox_deployments" + end + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] > 100 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling SandboxesApi.list_sandbox_deployments, must be smaller than or equal to 100.' + end + + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] < 1 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling SandboxesApi.list_sandbox_deployments, must be greater than or equal to 1.' + end + + # resource path + local_var_path = '/projects/{id}/sandboxes/{sandboxId}/deployments'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'sandboxId' + '}', CGI.escape(sandbox_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil? + query_params[:'cursor'] = opts[:'cursor'] if !opts[:'cursor'].nil? + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxDeploymentPage' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.list_sandbox_deployments", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#list_sandbox_deployments\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # List available sandbox presets + # @param [Hash] opts the optional parameters + # @return [SandboxPresetList] + def list_sandbox_presets(opts = {}) + data, _status_code, _headers = list_sandbox_presets_with_http_info(opts) + data + end + + # List available sandbox presets + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxPresetList, Integer, Hash)>] SandboxPresetList data, response status code and response headers + def list_sandbox_presets_with_http_info(opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.list_sandbox_presets ...' + end + # resource path + local_var_path = '/sandboxes/presets' + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxPresetList' + + # auth_names + auth_names = opts[:debug_auth_names] || [] + + new_options = opts.merge( + :operation => :"SandboxesApi.list_sandbox_presets", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#list_sandbox_presets\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # List project sandbox sessions + # @param id [String] + # @param [Hash] opts the optional parameters + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :cursor Opaque keyset pagination cursor from a previous response's `next_cursor` — pages forward. Mutually exclusive with `page` and `ending_before`; combining them returns 400. When supplied, the request's `search` and `limit` must match the values bound to the cursor or the request returns 400. + # @return [SandboxSessionPage] + def list_sandbox_sessions(id, opts = {}) + data, _status_code, _headers = list_sandbox_sessions_with_http_info(id, opts) + data + end + + # List project sandbox sessions + # @param id [String] + # @param [Hash] opts the optional parameters + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :cursor Opaque keyset pagination cursor from a previous response's `next_cursor` — pages forward. Mutually exclusive with `page` and `ending_before`; combining them returns 400. When supplied, the request's `search` and `limit` must match the values bound to the cursor or the request returns 400. + # @return [Array<(SandboxSessionPage, Integer, Hash)>] SandboxSessionPage data, response status code and response headers + def list_sandbox_sessions_with_http_info(id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.list_sandbox_sessions ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.list_sandbox_sessions" + end + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] > 100 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling SandboxesApi.list_sandbox_sessions, must be smaller than or equal to 100.' + end + + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] < 1 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling SandboxesApi.list_sandbox_sessions, must be greater than or equal to 1.' + end + + # resource path + local_var_path = '/projects/{id}/sandbox-sessions'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil? + query_params[:'cursor'] = opts[:'cursor'] if !opts[:'cursor'].nil? + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxSessionPage' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.list_sandbox_sessions", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#list_sandbox_sessions\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # List sandbox templates + # @param id [String] + # @param [Hash] opts the optional parameters + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :cursor Opaque keyset pagination cursor from a previous response's `next_cursor` — pages forward. Mutually exclusive with `page` and `ending_before`; combining them returns 400. When supplied, the request's `search` and `limit` must match the values bound to the cursor or the request returns 400. + # @return [SandboxTemplatePage] + def list_sandboxes(id, opts = {}) + data, _status_code, _headers = list_sandboxes_with_http_info(id, opts) + data + end + + # List sandbox templates + # @param id [String] + # @param [Hash] opts the optional parameters + # @option opts [Integer] :limit Number of items per page (max 100) (default to 10) + # @option opts [String] :cursor Opaque keyset pagination cursor from a previous response's `next_cursor` — pages forward. Mutually exclusive with `page` and `ending_before`; combining them returns 400. When supplied, the request's `search` and `limit` must match the values bound to the cursor or the request returns 400. + # @return [Array<(SandboxTemplatePage, Integer, Hash)>] SandboxTemplatePage data, response status code and response headers + def list_sandboxes_with_http_info(id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.list_sandboxes ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.list_sandboxes" + end + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] > 100 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling SandboxesApi.list_sandboxes, must be smaller than or equal to 100.' + end + + if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] < 1 + fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling SandboxesApi.list_sandboxes, must be greater than or equal to 1.' + end + + # resource path + local_var_path = '/projects/{id}/sandboxes'.sub('{' + 'id' + '}', CGI.escape(id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil? + query_params[:'cursor'] = opts[:'cursor'] if !opts[:'cursor'].nil? + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxTemplatePage' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.list_sandboxes", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#list_sandboxes\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Read a workspace file + # @param session_id [String] + # @param sandbox_file_read_request [SandboxFileReadRequest] + # @param [Hash] opts the optional parameters + # @return [SandboxFileResult] + def read_sandbox_session_file(session_id, sandbox_file_read_request, opts = {}) + data, _status_code, _headers = read_sandbox_session_file_with_http_info(session_id, sandbox_file_read_request, opts) + data + end + + # Read a workspace file + # @param session_id [String] + # @param sandbox_file_read_request [SandboxFileReadRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxFileResult, Integer, Hash)>] SandboxFileResult data, response status code and response headers + def read_sandbox_session_file_with_http_info(session_id, sandbox_file_read_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.read_sandbox_session_file ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.read_sandbox_session_file" + end + # verify the required parameter 'sandbox_file_read_request' is set + if @api_client.config.client_side_validation && sandbox_file_read_request.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_file_read_request' when calling SandboxesApi.read_sandbox_session_file" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/files/read'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(sandbox_file_read_request) + + # return_type + return_type = opts[:debug_return_type] || 'SandboxFileResult' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'AuthUserAccessToken', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.read_sandbox_session_file", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#read_sandbox_session_file\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Resume a sandbox session + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [SandboxSession] + def resume_sandbox_session(session_id, opts = {}) + data, _status_code, _headers = resume_sandbox_session_with_http_info(session_id, opts) + data + end + + # Resume a sandbox session + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxSession, Integer, Hash)>] SandboxSession data, response status code and response headers + def resume_sandbox_session_with_http_info(session_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.resume_sandbox_session ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.resume_sandbox_session" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/resume'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxSession' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.resume_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#resume_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Revoke a project user session grant + # @param session_id [String] + # @param subject_id [String] + # @param [Hash] opts the optional parameters + # @return [nil] + def revoke_sandbox_session(session_id, subject_id, opts = {}) + revoke_sandbox_session_with_http_info(session_id, subject_id, opts) + nil + end + + # Revoke a project user session grant + # @param session_id [String] + # @param subject_id [String] + # @param [Hash] opts the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def revoke_sandbox_session_with_http_info(session_id, subject_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.revoke_sandbox_session ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.revoke_sandbox_session" + end + # verify the required parameter 'subject_id' is set + if @api_client.config.client_side_validation && subject_id.nil? + fail ArgumentError, "Missing the required parameter 'subject_id' when calling SandboxesApi.revoke_sandbox_session" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/grants/{subjectId}'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)).sub('{' + 'subjectId' + '}', CGI.escape(subject_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.revoke_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#revoke_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Suspend a sandbox session + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [SandboxSession] + def suspend_sandbox_session(session_id, opts = {}) + data, _status_code, _headers = suspend_sandbox_session_with_http_info(session_id, opts) + data + end + + # Suspend a sandbox session + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxSession, Integer, Hash)>] SandboxSession data, response status code and response headers + def suspend_sandbox_session_with_http_info(session_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.suspend_sandbox_session ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.suspend_sandbox_session" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/suspend'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxSession' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.suspend_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#suspend_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Request sandbox termination + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [SandboxSession] + def terminate_sandbox_session(session_id, opts = {}) + data, _status_code, _headers = terminate_sandbox_session_with_http_info(session_id, opts) + data + end + + # Request sandbox termination + # @param session_id [String] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxSession, Integer, Hash)>] SandboxSession data, response status code and response headers + def terminate_sandbox_session_with_http_info(session_id, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.terminate_sandbox_session ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.terminate_sandbox_session" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'SandboxSession' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.terminate_sandbox_session", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#terminate_sandbox_session\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Rename a sandbox template + # @param id [String] + # @param sandbox_id [String] + # @param update_sandbox_template_request [UpdateSandboxTemplateRequest] + # @param [Hash] opts the optional parameters + # @return [SandboxTemplate] + def update_sandbox(id, sandbox_id, update_sandbox_template_request, opts = {}) + data, _status_code, _headers = update_sandbox_with_http_info(id, sandbox_id, update_sandbox_template_request, opts) + data + end + + # Rename a sandbox template + # @param id [String] + # @param sandbox_id [String] + # @param update_sandbox_template_request [UpdateSandboxTemplateRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(SandboxTemplate, Integer, Hash)>] SandboxTemplate data, response status code and response headers + def update_sandbox_with_http_info(id, sandbox_id, update_sandbox_template_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.update_sandbox ...' + end + # verify the required parameter 'id' is set + if @api_client.config.client_side_validation && id.nil? + fail ArgumentError, "Missing the required parameter 'id' when calling SandboxesApi.update_sandbox" + end + # verify the required parameter 'sandbox_id' is set + if @api_client.config.client_side_validation && sandbox_id.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_id' when calling SandboxesApi.update_sandbox" + end + # verify the required parameter 'update_sandbox_template_request' is set + if @api_client.config.client_side_validation && update_sandbox_template_request.nil? + fail ArgumentError, "Missing the required parameter 'update_sandbox_template_request' when calling SandboxesApi.update_sandbox" + end + # resource path + local_var_path = '/projects/{id}/sandboxes/{sandboxId}'.sub('{' + 'id' + '}', CGI.escape(id.to_s)).sub('{' + 'sandboxId' + '}', CGI.escape(sandbox_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(update_sandbox_template_request) + + # return_type + return_type = opts[:debug_return_type] || 'SandboxTemplate' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.update_sandbox", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:PATCH, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#update_sandbox\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Write a workspace file + # @param session_id [String] + # @param sandbox_file_write_request [SandboxFileWriteRequest] + # @param [Hash] opts the optional parameters + # @return [nil] + def write_sandbox_session_file(session_id, sandbox_file_write_request, opts = {}) + write_sandbox_session_file_with_http_info(session_id, sandbox_file_write_request, opts) + nil + end + + # Write a workspace file + # @param session_id [String] + # @param sandbox_file_write_request [SandboxFileWriteRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def write_sandbox_session_file_with_http_info(session_id, sandbox_file_write_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SandboxesApi.write_sandbox_session_file ...' + end + # verify the required parameter 'session_id' is set + if @api_client.config.client_side_validation && session_id.nil? + fail ArgumentError, "Missing the required parameter 'session_id' when calling SandboxesApi.write_sandbox_session_file" + end + # verify the required parameter 'sandbox_file_write_request' is set + if @api_client.config.client_side_validation && sandbox_file_write_request.nil? + fail ArgumentError, "Missing the required parameter 'sandbox_file_write_request' when calling SandboxesApi.write_sandbox_session_file" + end + # resource path + local_var_path = '/sandbox-sessions/{sessionId}/files/write'.sub('{' + 'sessionId' + '}', CGI.escape(session_id.to_s)) + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(sandbox_file_write_request) + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || ['ServiceRoleKey', 'AuthUserAccessToken', 'UserToken'] + + new_options = opts.merge( + :operation => :"SandboxesApi.write_sandbox_session_file", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SandboxesApi#write_sandbox_session_file\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + end +end diff --git a/lib/volcano/generated/lib/volcano-generated/api/service_keys_api.rb b/lib/volcano/generated/lib/volcano-generated/api/service_keys_api.rb index 8a816c56..7463f349 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/service_keys_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/service_keys_api.rb @@ -74,7 +74,7 @@ def create_service_key_with_http_info(id, create_service_key_request, opts = {}) return_type = opts[:debug_return_type] || 'ServiceKey' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ServiceKeysApi.create_service_key", @@ -141,7 +141,7 @@ def delete_service_key_with_http_info(id, key_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ServiceKeysApi.delete_service_key", @@ -210,7 +210,7 @@ def get_service_key_with_http_info(id, key_id, opts = {}) return_type = opts[:debug_return_type] || 'ServiceKey' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ServiceKeysApi.get_service_key", @@ -311,7 +311,7 @@ def list_service_keys_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedServiceKeys' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ServiceKeysApi.list_service_keys", @@ -331,7 +331,7 @@ def list_service_keys_with_http_info(id, opts = {}) end # Regenerate service key - # Generate new JWT value for existing key. The old key is immediately invalidated. Update your backend services with the new key before regenerating in production. + # Generate new JWT value for existing key. The old key stops working within a few seconds. Update your backend services with the new key before regenerating in production. # @param id [String] Project ID # @param key_id [String] # @param [Hash] opts the optional parameters @@ -342,7 +342,7 @@ def regenerate_service_key(id, key_id, opts = {}) end # Regenerate service key - # Generate new JWT value for existing key. The old key is immediately invalidated. Update your backend services with the new key before regenerating in production. + # Generate new JWT value for existing key. The old key stops working within a few seconds. Update your backend services with the new key before regenerating in production. # @param id [String] Project ID # @param key_id [String] # @param [Hash] opts the optional parameters @@ -380,7 +380,7 @@ def regenerate_service_key_with_http_info(id, key_id, opts = {}) return_type = opts[:debug_return_type] || 'ServiceKey' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"ServiceKeysApi.regenerate_service_key", diff --git a/lib/volcano/generated/lib/volcano-generated/api/storage_admin_api.rb b/lib/volcano/generated/lib/volcano-generated/api/storage_admin_api.rb index 8dd6d4e1..5f5b8ceb 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/storage_admin_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/storage_admin_api.rb @@ -63,7 +63,7 @@ def get_storage_stats_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'StorageStats' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StorageAdminApi.get_storage_stats", @@ -167,7 +167,7 @@ def list_storage_objects_admin_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ListStorageObjectsAdmin200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StorageAdminApi.list_storage_objects_admin", diff --git a/lib/volcano/generated/lib/volcano-generated/api/storage_buckets_api.rb b/lib/volcano/generated/lib/volcano-generated/api/storage_buckets_api.rb index fcf44d8f..dba91207 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/storage_buckets_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/storage_buckets_api.rb @@ -72,7 +72,7 @@ def create_storage_bucket_with_http_info(id, create_storage_bucket_request, opts return_type = opts[:debug_return_type] || 'StorageBucket' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StorageBucketsApi.create_storage_bucket", @@ -150,7 +150,7 @@ def delete_storage_bucket_with_http_info(id, bucket_name, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StorageBucketsApi.delete_storage_bucket", @@ -230,7 +230,7 @@ def get_storage_bucket_with_http_info(id, bucket_name, opts = {}) return_type = opts[:debug_return_type] || 'StorageBucket' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StorageBucketsApi.get_storage_bucket", @@ -324,7 +324,7 @@ def list_storage_buckets_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'ListStorageBuckets200Response' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StorageBucketsApi.list_storage_buckets", @@ -415,7 +415,7 @@ def update_storage_bucket_with_http_info(id, bucket_name, update_storage_bucket_ return_type = opts[:debug_return_type] || 'StorageBucket' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StorageBucketsApi.update_storage_bucket", diff --git a/lib/volcano/generated/lib/volcano-generated/api/storage_policies_api.rb b/lib/volcano/generated/lib/volcano-generated/api/storage_policies_api.rb index 014eb23a..5c53c752 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/storage_policies_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/storage_policies_api.rb @@ -91,7 +91,7 @@ def create_storage_policy_with_http_info(id, bucket_name, create_storage_policy_ return_type = opts[:debug_return_type] || 'StoragePolicy' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StoragePoliciesApi.create_storage_policy", @@ -175,7 +175,7 @@ def delete_storage_policy_with_http_info(id, bucket_name, policy_id, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StoragePoliciesApi.delete_storage_policy", @@ -255,7 +255,7 @@ def list_storage_policies_with_http_info(id, bucket_name, opts = {}) return_type = opts[:debug_return_type] || 'Array' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"StoragePoliciesApi.list_storage_policies", diff --git a/lib/volcano/generated/lib/volcano-generated/api/system_api.rb b/lib/volcano/generated/lib/volcano-generated/api/system_api.rb index 0f15388e..4c7cdcd1 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/system_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/system_api.rb @@ -19,6 +19,314 @@ class SystemApi def initialize(api_client = ApiClient.default) @api_client = api_client end + # Model Context Protocol endpoint + # Streamable-HTTP MCP endpoint: one JSON-RPC 2.0 object per request, one response per request. There is no server-to-client stream, so a `GET` returns `405`, and a batched array is rejected. Authenticated with a **project access token**. The endpoint takes its project from the credential, so a platform token is refused with `403` — it names no project, and letting a tool argument choose one would hand an agent its own blast radius. Scope carries over from the REST API. A `read_only` token is not offered mutating tools or credential-returning reads, and is refused if it calls one anyway. Revoking the token ends MCP access on the same path it ends API access. Methods: `initialize`, `notifications/initialized`, `ping`, `tools/list`, `tools/call`. See the [MCP guide](https://docs.volcano.dev/platform/interfaces/mcp) for the tool surface and client configuration. + # @param call_mcp_request [CallMCPRequest] + # @param [Hash] opts the optional parameters + # @return [CallMCP200Response] + def call_mcp(call_mcp_request, opts = {}) + data, _status_code, _headers = call_mcp_with_http_info(call_mcp_request, opts) + data + end + + # Model Context Protocol endpoint + # Streamable-HTTP MCP endpoint: one JSON-RPC 2.0 object per request, one response per request. There is no server-to-client stream, so a `GET` returns `405`, and a batched array is rejected. Authenticated with a **project access token**. The endpoint takes its project from the credential, so a platform token is refused with `403` — it names no project, and letting a tool argument choose one would hand an agent its own blast radius. Scope carries over from the REST API. A `read_only` token is not offered mutating tools or credential-returning reads, and is refused if it calls one anyway. Revoking the token ends MCP access on the same path it ends API access. Methods: `initialize`, `notifications/initialized`, `ping`, `tools/list`, `tools/call`. See the [MCP guide](https://docs.volcano.dev/platform/interfaces/mcp) for the tool surface and client configuration. + # @param call_mcp_request [CallMCPRequest] + # @param [Hash] opts the optional parameters + # @return [Array<(CallMCP200Response, Integer, Hash)>] CallMCP200Response data, response status code and response headers + def call_mcp_with_http_info(call_mcp_request, opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SystemApi.call_mcp ...' + end + # verify the required parameter 'call_mcp_request' is set + if @api_client.config.client_side_validation && call_mcp_request.nil? + fail ArgumentError, "Missing the required parameter 'call_mcp_request' when calling SystemApi.call_mcp" + end + # resource path + local_var_path = '/mcp' + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/json']) + if !content_type.nil? + header_params['Content-Type'] = content_type + end + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] || @api_client.object_to_http_body(call_mcp_request) + + # return_type + return_type = opts[:debug_return_type] || 'CallMCP200Response' + + # auth_names + auth_names = opts[:debug_auth_names] || ['ProjectAccessToken'] + + new_options = opts.merge( + :operation => :"SystemApi.call_mcp", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SystemApi#call_mcp\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Fetch the OpenAPI specification as JSON + # Returns this specification as a self-contained JSON document, with every reference resolved. It is generated from the same document the server validates requests against, so a client generated from it cannot describe a different API than the one that answers. No credential is required: a client generator fetches this by URL before its user has a token, and every path here is already published in the API reference. The response carries a strong `ETag`; send it back as `If-None-Match` to get `304 Not Modified` instead of the whole document. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [Hash] + def get_open_api_spec_json(opts = {}) + data, _status_code, _headers = get_open_api_spec_json_with_http_info(opts) + data + end + + # Fetch the OpenAPI specification as JSON + # Returns this specification as a self-contained JSON document, with every reference resolved. It is generated from the same document the server validates requests against, so a client generated from it cannot describe a different API than the one that answers. No credential is required: a client generator fetches this by URL before its user has a token, and every path here is already published in the API reference. The response carries a strong `ETag`; send it back as `If-None-Match` to get `304 Not Modified` instead of the whole document. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [Array<(Hash, Integer, Hash)>] Hash data, response status code and response headers + def get_open_api_spec_json_with_http_info(opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SystemApi.get_open_api_spec_json ...' + end + # resource path + local_var_path = '/openapi.json' + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + header_params[:'If-None-Match'] = opts[:'if_none_match'] if !opts[:'if_none_match'].nil? + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'Hash' + + # auth_names + auth_names = opts[:debug_auth_names] || [] + + new_options = opts.merge( + :operation => :"SystemApi.get_open_api_spec_json", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SystemApi#get_open_api_spec_json\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Fetch the OpenAPI specification as YAML + # The same document as `/openapi.json`, serialized as YAML for tools that prefer it. See that operation for caching and authentication notes. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [Hash] + def get_open_api_spec_yaml(opts = {}) + data, _status_code, _headers = get_open_api_spec_yaml_with_http_info(opts) + data + end + + # Fetch the OpenAPI specification as YAML + # The same document as `/openapi.json`, serialized as YAML for tools that prefer it. See that operation for caching and authentication notes. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [Array<(Hash, Integer, Hash)>] Hash data, response status code and response headers + def get_open_api_spec_yaml_with_http_info(opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SystemApi.get_open_api_spec_yaml ...' + end + # resource path + local_var_path = '/openapi.yaml' + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/yaml', 'application/json']) unless header_params['Accept'] + header_params[:'If-None-Match'] = opts[:'if_none_match'] if !opts[:'if_none_match'].nil? + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] || 'Hash' + + # auth_names + auth_names = opts[:debug_auth_names] || [] + + new_options = opts.merge( + :operation => :"SystemApi.get_open_api_spec_yaml", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SystemApi#get_open_api_spec_yaml\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Check the JSON OpenAPI specification + # The headers `GET /openapi.json` would return, so a cache can pick up the current `ETag` without transferring the document. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [nil] + def head_open_api_spec_json(opts = {}) + head_open_api_spec_json_with_http_info(opts) + nil + end + + # Check the JSON OpenAPI specification + # The headers `GET /openapi.json` would return, so a cache can pick up the current `ETag` without transferring the document. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def head_open_api_spec_json_with_http_info(opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SystemApi.head_open_api_spec_json ...' + end + # resource path + local_var_path = '/openapi.json' + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + header_params[:'If-None-Match'] = opts[:'if_none_match'] if !opts[:'if_none_match'].nil? + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || [] + + new_options = opts.merge( + :operation => :"SystemApi.head_open_api_spec_json", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:HEAD, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SystemApi#head_open_api_spec_json\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + + # Check the YAML OpenAPI specification + # The headers `GET /openapi.yaml` would return, so a cache can pick up the current `ETag` without transferring the document. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [nil] + def head_open_api_spec_yaml(opts = {}) + head_open_api_spec_yaml_with_http_info(opts) + nil + end + + # Check the YAML OpenAPI specification + # The headers `GET /openapi.yaml` would return, so a cache can pick up the current `ETag` without transferring the document. + # @param [Hash] opts the optional parameters + # @option opts [String] :if_none_match Entity tag from an earlier response, returning `304 Not Modified` while it still matches. Accepts the full condition: `*`, a comma-separated list, and weak tags of the form `W/\"tag\"`. + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def head_open_api_spec_yaml_with_http_info(opts = {}) + if @api_client.config.debugging + @api_client.config.logger.debug 'Calling API: SystemApi.head_open_api_spec_yaml ...' + end + # resource path + local_var_path = '/openapi.yaml' + + # query parameters + query_params = opts[:query_params] || {} + + # header parameters + header_params = opts[:header_params] || {} + # HTTP header 'Accept' (if needed) + header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept'] + header_params[:'If-None-Match'] = opts[:'if_none_match'] if !opts[:'if_none_match'].nil? + + # form parameters + form_params = opts[:form_params] || {} + + # http body (model) + post_body = opts[:debug_body] + + # return_type + return_type = opts[:debug_return_type] + + # auth_names + auth_names = opts[:debug_auth_names] || [] + + new_options = opts.merge( + :operation => :"SystemApi.head_open_api_spec_yaml", + :header_params => header_params, + :query_params => query_params, + :form_params => form_params, + :body => post_body, + :auth_names => auth_names, + :return_type => return_type + ) + + data, status_code, headers = @api_client.call_api(:HEAD, local_var_path, new_options) + if @api_client.config.debugging + @api_client.config.logger.debug "API called: SystemApi#head_open_api_spec_yaml\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" + end + return data, status_code, headers + end + # Health check endpoint # Returns server health status. Used for load balancer and monitoring checks. # @param [Hash] opts the optional parameters diff --git a/lib/volcano/generated/lib/volcano-generated/api/variables_api.rb b/lib/volcano/generated/lib/volcano-generated/api/variables_api.rb index 82522d03..c669b0f9 100644 --- a/lib/volcano/generated/lib/volcano-generated/api/variables_api.rb +++ b/lib/volcano/generated/lib/volcano-generated/api/variables_api.rb @@ -74,7 +74,7 @@ def create_variable_with_http_info(id, create_variable_request, opts = {}) return_type = opts[:debug_return_type] || 'Variable' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"VariablesApi.create_variable", @@ -96,7 +96,7 @@ def create_variable_with_http_info(id, create_variable_request, opts = {}) # Delete a variable # Deletes a project-level environment variable and triggers asynchronous propagation of the removal to deployed functions and frontends in the project's configured regions. # @param id [String] Project ID - # @param name [String] Variable name + # @param name [String] Variable name. Function runtime names such as AWS_REGION are reserved and cannot be updated. # @param [Hash] opts the optional parameters # @return [nil] def delete_variable(id, name, opts = {}) @@ -107,7 +107,7 @@ def delete_variable(id, name, opts = {}) # Delete a variable # Deletes a project-level environment variable and triggers asynchronous propagation of the removal to deployed functions and frontends in the project's configured regions. # @param id [String] Project ID - # @param name [String] Variable name + # @param name [String] Variable name. Function runtime names such as AWS_REGION are reserved and cannot be updated. # @param [Hash] opts the optional parameters # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers def delete_variable_with_http_info(id, name, opts = {}) @@ -156,7 +156,7 @@ def delete_variable_with_http_info(id, name, opts = {}) return_type = opts[:debug_return_type] # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"VariablesApi.delete_variable", @@ -178,7 +178,7 @@ def delete_variable_with_http_info(id, name, opts = {}) # Get variable by name # Returns a project-level environment variable used by deployed functions and frontends. # @param id [String] Project ID - # @param name [String] Variable name + # @param name [String] Variable name. Function runtime names such as AWS_REGION are reserved and cannot be updated. # @param [Hash] opts the optional parameters # @return [Variable] def get_variable(id, name, opts = {}) @@ -189,7 +189,7 @@ def get_variable(id, name, opts = {}) # Get variable by name # Returns a project-level environment variable used by deployed functions and frontends. # @param id [String] Project ID - # @param name [String] Variable name + # @param name [String] Variable name. Function runtime names such as AWS_REGION are reserved and cannot be updated. # @param [Hash] opts the optional parameters # @return [Array<(Variable, Integer, Hash)>] Variable data, response status code and response headers def get_variable_with_http_info(id, name, opts = {}) @@ -238,7 +238,7 @@ def get_variable_with_http_info(id, name, opts = {}) return_type = opts[:debug_return_type] || 'Variable' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"VariablesApi.get_variable", @@ -339,7 +339,7 @@ def list_variables_with_http_info(id, opts = {}) return_type = opts[:debug_return_type] || 'PaginatedVariables' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"VariablesApi.list_variables", @@ -361,7 +361,7 @@ def list_variables_with_http_info(id, opts = {}) # Update a variable # Updates a project-level environment variable and triggers asynchronous propagation to deployed functions and frontends in the project's configured regions. # @param id [String] Project ID - # @param name [String] Variable name + # @param name [String] Variable name. Function runtime names such as AWS_REGION are reserved and cannot be updated. # @param update_variable_request [UpdateVariableRequest] # @param [Hash] opts the optional parameters # @return [Variable] @@ -373,7 +373,7 @@ def update_variable(id, name, update_variable_request, opts = {}) # Update a variable # Updates a project-level environment variable and triggers asynchronous propagation to deployed functions and frontends in the project's configured regions. # @param id [String] Project ID - # @param name [String] Variable name + # @param name [String] Variable name. Function runtime names such as AWS_REGION are reserved and cannot be updated. # @param update_variable_request [UpdateVariableRequest] # @param [Hash] opts the optional parameters # @return [Array<(Variable, Integer, Hash)>] Variable data, response status code and response headers @@ -432,7 +432,7 @@ def update_variable_with_http_info(id, name, update_variable_request, opts = {}) return_type = opts[:debug_return_type] || 'Variable' # auth_names - auth_names = opts[:debug_auth_names] || ['UserToken'] + auth_names = opts[:debug_auth_names] || ['UserToken', 'ProjectAccessToken'] new_options = opts.merge( :operation => :"VariablesApi.update_variable", diff --git a/lib/volcano/generated/lib/volcano-generated/configuration.rb b/lib/volcano/generated/lib/volcano-generated/configuration.rb index 0c605526..efb22e7b 100644 --- a/lib/volcano/generated/lib/volcano-generated/configuration.rb +++ b/lib/volcano/generated/lib/volcano-generated/configuration.rb @@ -272,7 +272,15 @@ def auth_settings { type: 'bearer', in: 'header', - format: 'JWT', + format: 'opaque', + key: 'Authorization', + value: "Bearer #{access_token_with_refresh}" + }, + 'ProjectAccessToken' => + { + type: 'bearer', + in: 'header', + format: 'opaque', key: 'Authorization', value: "Bearer #{access_token_with_refresh}" }, diff --git a/lib/volcano/generated/lib/volcano-generated/models/auth_insights_series_point.rb b/lib/volcano/generated/lib/volcano-generated/models/auth_insights_series_point.rb index 8aad0ba7..e5c1cf1f 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/auth_insights_series_point.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/auth_insights_series_point.rb @@ -17,7 +17,7 @@ module Volcano::Generated class AuthInsightsSeriesPoint < ApiModelBase attr_accessor :bucket_start - # Accounts created during the bucket. + # Accounts created during the bucket that still exist. attr_accessor :signups # Successful session creations during the bucket. diff --git a/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response.rb b/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response.rb new file mode 100644 index 00000000..307ea872 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response.rb @@ -0,0 +1,220 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class CallMCP200Response < ApiModelBase + attr_accessor :jsonrpc + + attr_accessor :id + + attr_accessor :result + + attr_accessor :error + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'jsonrpc' => :'jsonrpc', + :'id' => :'id', + :'result' => :'result', + :'error' => :'error' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'jsonrpc' => :'String', + :'id' => :'CallMCP200ResponseId', + :'result' => :'Hash', + :'error' => :'CallMCP200ResponseError' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + :'id', + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CallMCP200Response` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CallMCP200Response`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'jsonrpc') + self.jsonrpc = attributes[:'jsonrpc'] + else + self.jsonrpc = nil + end + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'result') + if (value = attributes[:'result']).is_a?(Hash) + self.result = value + end + end + + if attributes.key?(:'error') + self.error = attributes[:'error'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @jsonrpc.nil? + invalid_properties.push('invalid value for "jsonrpc", jsonrpc cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @jsonrpc.nil? + jsonrpc_validator = EnumAttributeValidator.new('String', ["2.0"]) + return false unless jsonrpc_validator.valid?(@jsonrpc) + true + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] jsonrpc Object to be assigned + def jsonrpc=(jsonrpc) + validator = EnumAttributeValidator.new('String', ["2.0"]) + unless validator.valid?(jsonrpc) + fail ArgumentError, "invalid value for \"jsonrpc\", must be one of #{validator.allowable_values}." + end + @jsonrpc = jsonrpc + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + jsonrpc == o.jsonrpc && + id == o.id && + result == o.result && + error == o.error + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [jsonrpc, id, result, error].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_error.rb b/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_error.rb new file mode 100644 index 00000000..cd5354b5 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_error.rb @@ -0,0 +1,190 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class CallMCP200ResponseError < ApiModelBase + attr_accessor :code + + attr_accessor :message + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'code' => :'code', + :'message' => :'message' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'code' => :'Integer', + :'message' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CallMCP200ResponseError` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CallMCP200ResponseError`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'code') + self.code = attributes[:'code'] + else + self.code = nil + end + + if attributes.key?(:'message') + self.message = attributes[:'message'] + else + self.message = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @code.nil? + invalid_properties.push('invalid value for "code", code cannot be nil.') + end + + if @message.nil? + invalid_properties.push('invalid value for "message", message cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @code.nil? + return false if @message.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] code Value to be assigned + def code=(code) + if code.nil? + fail ArgumentError, 'code cannot be nil' + end + + @code = code + end + + # Custom attribute writer method with validation + # @param [Object] message Value to be assigned + def message=(message) + if message.nil? + fail ArgumentError, 'message cannot be nil' + end + + @message = message + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + code == o.code && + message == o.message + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [code, message].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_id.rb b/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_id.rb new file mode 100644 index 00000000..d008fbf5 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/call_mcp200_response_id.rb @@ -0,0 +1,105 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # Echoes the request's id. Null when the request could not be read well enough to determine one. + module CallMCP200ResponseId + class << self + # List of class defined in oneOf (OpenAPI v3) + def openapi_one_of + [ + :'Integer', + :'String' + ] + end + + # Builds the object + # @param [Mixed] Data to be matched against the list of oneOf items + # @return [Object] Returns the model or the data itself + def build(data) + # Go through the list of oneOf items and attempt to identify the appropriate one. + # Note: + # - We do not attempt to check whether exactly one item matches. + # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 }) + # due to the way the deserialization is made in the base_object template (it just casts without verifying). + # - TODO: scalar values are de facto behaving as if they were nullable. + # - TODO: logging when debugging is set. + openapi_one_of.each do |klass| + begin + next if klass == :AnyType # "nullable: true" + return find_and_cast_into_type(klass, data) + rescue # rescue all errors so we keep iterating even if the current item lookup raises + end + end + + openapi_one_of.include?(:AnyType) ? data : nil + end + + private + + SchemaMismatchError = Class.new(StandardError) + + # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse. + def find_and_cast_into_type(klass, data) + return if data.nil? + + case klass.to_s + when 'Boolean' + return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass) + when 'Float' + return data if data.instance_of?(Float) + when 'Integer' + return data if data.instance_of?(Integer) + when 'Time' + return Time.parse(data) + when 'Date' + return Date.iso8601(data) + when 'String' + return data if data.instance_of?(String) + when 'Object' # "type: object" + return data if data.instance_of?(Hash) + when /\AArray<(?.+)>\z/ # "type: array" + if data.instance_of?(Array) + sub_type = Regexp.last_match[:sub_type] + return data.map { |item| find_and_cast_into_type(sub_type, item) } + end + when /\AHash.+)>\z/ # "type: object" with "additionalProperties: { ... }" + if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) } + sub_type = Regexp.last_match[:sub_type] + return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) } + end + else # model + const = Object.const_get('Volcano::Generated').const_get(klass) + if const + if const.respond_to?(:openapi_one_of) # nested oneOf model + model = const.build(data) + return model unless model.nil? + else + # raise if data contains keys that are not known to the model + raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty? + model = const.build_from_hash(data) + return model if model + end + end + end + + raise # if no match by now, raise + rescue + raise SchemaMismatchError, "#{data} doesn't match the #{klass} type" + end + end + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/call_mcp_request.rb b/lib/volcano/generated/lib/volcano-generated/models/call_mcp_request.rb new file mode 100644 index 00000000..77e264b7 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/call_mcp_request.rb @@ -0,0 +1,236 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # A JSON-RPC 2.0 request object. + class CallMCPRequest < ApiModelBase + attr_accessor :jsonrpc + + # The MCP method to call. + attr_accessor :method + + attr_accessor :id + + attr_accessor :params + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'jsonrpc' => :'jsonrpc', + :'method' => :'method', + :'id' => :'id', + :'params' => :'params' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'jsonrpc' => :'String', + :'method' => :'String', + :'id' => :'CallMCPRequestId', + :'params' => :'Hash' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CallMCPRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CallMCPRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'jsonrpc') + self.jsonrpc = attributes[:'jsonrpc'] + else + self.jsonrpc = nil + end + + if attributes.key?(:'method') + self.method = attributes[:'method'] + else + self.method = nil + end + + if attributes.key?(:'id') + self.id = attributes[:'id'] + end + + if attributes.key?(:'params') + if (value = attributes[:'params']).is_a?(Hash) + self.params = value + end + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @jsonrpc.nil? + invalid_properties.push('invalid value for "jsonrpc", jsonrpc cannot be nil.') + end + + if @method.nil? + invalid_properties.push('invalid value for "method", method cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @jsonrpc.nil? + jsonrpc_validator = EnumAttributeValidator.new('String', ["2.0"]) + return false unless jsonrpc_validator.valid?(@jsonrpc) + return false if @method.nil? + true + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] jsonrpc Object to be assigned + def jsonrpc=(jsonrpc) + validator = EnumAttributeValidator.new('String', ["2.0"]) + unless validator.valid?(jsonrpc) + fail ArgumentError, "invalid value for \"jsonrpc\", must be one of #{validator.allowable_values}." + end + @jsonrpc = jsonrpc + end + + # Custom attribute writer method with validation + # @param [Object] method Value to be assigned + def method=(method) + if method.nil? + fail ArgumentError, 'method cannot be nil' + end + + @method = method + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + jsonrpc == o.jsonrpc && + method == o.method && + id == o.id && + params == o.params + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [jsonrpc, method, id, params].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/call_mcp_request_id.rb b/lib/volcano/generated/lib/volcano-generated/models/call_mcp_request_id.rb new file mode 100644 index 00000000..57885ad7 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/call_mcp_request_id.rb @@ -0,0 +1,105 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # Request identifier, echoed verbatim. Omit it to send a notification, which is answered with `202` and no body. + module CallMCPRequestId + class << self + # List of class defined in oneOf (OpenAPI v3) + def openapi_one_of + [ + :'Integer', + :'String' + ] + end + + # Builds the object + # @param [Mixed] Data to be matched against the list of oneOf items + # @return [Object] Returns the model or the data itself + def build(data) + # Go through the list of oneOf items and attempt to identify the appropriate one. + # Note: + # - We do not attempt to check whether exactly one item matches. + # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 }) + # due to the way the deserialization is made in the base_object template (it just casts without verifying). + # - TODO: scalar values are de facto behaving as if they were nullable. + # - TODO: logging when debugging is set. + openapi_one_of.each do |klass| + begin + next if klass == :AnyType # "nullable: true" + return find_and_cast_into_type(klass, data) + rescue # rescue all errors so we keep iterating even if the current item lookup raises + end + end + + openapi_one_of.include?(:AnyType) ? data : nil + end + + private + + SchemaMismatchError = Class.new(StandardError) + + # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse. + def find_and_cast_into_type(klass, data) + return if data.nil? + + case klass.to_s + when 'Boolean' + return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass) + when 'Float' + return data if data.instance_of?(Float) + when 'Integer' + return data if data.instance_of?(Integer) + when 'Time' + return Time.parse(data) + when 'Date' + return Date.iso8601(data) + when 'String' + return data if data.instance_of?(String) + when 'Object' # "type: object" + return data if data.instance_of?(Hash) + when /\AArray<(?.+)>\z/ # "type: array" + if data.instance_of?(Array) + sub_type = Regexp.last_match[:sub_type] + return data.map { |item| find_and_cast_into_type(sub_type, item) } + end + when /\AHash.+)>\z/ # "type: object" with "additionalProperties: { ... }" + if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) } + sub_type = Regexp.last_match[:sub_type] + return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) } + end + else # model + const = Object.const_get('Volcano::Generated').const_get(klass) + if const + if const.respond_to?(:openapi_one_of) # nested oneOf model + model = const.build(data) + return model unless model.nil? + else + # raise if data contains keys that are not known to the model + raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty? + model = const.build_from_hash(data) + return model if model + end + end + end + + raise # if no match by now, raise + rescue + raise SchemaMismatchError, "#{data} doesn't match the #{klass} type" + end + end + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/create_database_request.rb b/lib/volcano/generated/lib/volcano-generated/models/create_database_request.rb index b66b90c0..39fb5047 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/create_database_request.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/create_database_request.rb @@ -19,7 +19,7 @@ class CreateDatabaseRequest < ApiModelBase # Database name (must be unique within project) attr_accessor :name - # Region for database hosting. The accepted values are the regions this environment runs in, so read them from `GET /databases/regions` rather than hardcoding a list. A region the environment does not offer is rejected with 400. + # Region for database hosting, such as `us-east-1`. The accepted values are the regions this environment runs in, so read them from `GET /databases/regions` rather than hardcoding a list. A region the environment does not offer is rejected with 400. Region IDs issued by earlier versions of the API are still accepted. attr_accessor :region # PostgreSQL major version diff --git a/lib/volcano/generated/lib/volcano-generated/models/create_frontend_function_route_request.rb b/lib/volcano/generated/lib/volcano-generated/models/create_frontend_function_route_request.rb new file mode 100644 index 00000000..68b531f0 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/create_frontend_function_route_request.rb @@ -0,0 +1,230 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class CreateFrontendFunctionRouteRequest < ApiModelBase + attr_accessor :function_id + + attr_accessor :path_prefix + + attr_accessor :strip_prefix + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'function_id' => :'function_id', + :'path_prefix' => :'path_prefix', + :'strip_prefix' => :'strip_prefix' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'function_id' => :'String', + :'path_prefix' => :'String', + :'strip_prefix' => :'Boolean' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CreateFrontendFunctionRouteRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CreateFrontendFunctionRouteRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'function_id') + self.function_id = attributes[:'function_id'] + else + self.function_id = nil + end + + if attributes.key?(:'path_prefix') + self.path_prefix = attributes[:'path_prefix'] + else + self.path_prefix = nil + end + + if attributes.key?(:'strip_prefix') + self.strip_prefix = attributes[:'strip_prefix'] + else + self.strip_prefix = false + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @function_id.nil? + invalid_properties.push('invalid value for "function_id", function_id cannot be nil.') + end + + if @path_prefix.nil? + invalid_properties.push('invalid value for "path_prefix", path_prefix cannot be nil.') + end + + if @path_prefix.to_s.length > 512 + invalid_properties.push('invalid value for "path_prefix", the character length must be smaller than or equal to 512.') + end + + if @path_prefix.to_s.length < 2 + invalid_properties.push('invalid value for "path_prefix", the character length must be greater than or equal to 2.') + end + + pattern = Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + if @path_prefix !~ pattern + invalid_properties.push("invalid value for \"path_prefix\", must conform to the pattern #{pattern}.") + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @function_id.nil? + return false if @path_prefix.nil? + return false if @path_prefix.to_s.length > 512 + return false if @path_prefix.to_s.length < 2 + return false if @path_prefix !~ Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + true + end + + # Custom attribute writer method with validation + # @param [Object] function_id Value to be assigned + def function_id=(function_id) + if function_id.nil? + fail ArgumentError, 'function_id cannot be nil' + end + + @function_id = function_id + end + + # Custom attribute writer method with validation + # @param [Object] path_prefix Value to be assigned + def path_prefix=(path_prefix) + if path_prefix.nil? + fail ArgumentError, 'path_prefix cannot be nil' + end + + if path_prefix.to_s.length > 512 + fail ArgumentError, 'invalid value for "path_prefix", the character length must be smaller than or equal to 512.' + end + + if path_prefix.to_s.length < 2 + fail ArgumentError, 'invalid value for "path_prefix", the character length must be greater than or equal to 2.' + end + + pattern = Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + if path_prefix !~ pattern + fail ArgumentError, "invalid value for \"path_prefix\", must conform to the pattern #{pattern}." + end + + @path_prefix = path_prefix + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + function_id == o.function_id && + path_prefix == o.path_prefix && + strip_prefix == o.strip_prefix + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [function_id, path_prefix, strip_prefix].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/create_project_access_token_request.rb b/lib/volcano/generated/lib/volcano-generated/models/create_project_access_token_request.rb new file mode 100644 index 00000000..677846df --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/create_project_access_token_request.rb @@ -0,0 +1,241 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class CreateProjectAccessTokenRequest < ApiModelBase + # Held by any of the project's tokens you have not revoked, including one that has expired. Creating a duplicate returns 409 with code `access_token_name_exists`; revoking the holder frees the name, so a rotation can keep the name its caller already references. + attr_accessor :name + + attr_accessor :scope + + # Omit for a token that does not expire. + attr_accessor :expires_at + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'name' => :'name', + :'scope' => :'scope', + :'expires_at' => :'expires_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'name' => :'String', + :'scope' => :'ProjectAccessTokenScope', + :'expires_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CreateProjectAccessTokenRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CreateProjectAccessTokenRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'name') + self.name = attributes[:'name'] + else + self.name = nil + end + + if attributes.key?(:'scope') + self.scope = attributes[:'scope'] + else + self.scope = nil + end + + if attributes.key?(:'expires_at') + self.expires_at = attributes[:'expires_at'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @name.nil? + invalid_properties.push('invalid value for "name", name cannot be nil.') + end + + if @name.to_s.length > 100 + invalid_properties.push('invalid value for "name", the character length must be smaller than or equal to 100.') + end + + if @name.to_s.length < 1 + invalid_properties.push('invalid value for "name", the character length must be greater than or equal to 1.') + end + + if @scope.nil? + invalid_properties.push('invalid value for "scope", scope cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @name.nil? + return false if @name.to_s.length > 100 + return false if @name.to_s.length < 1 + return false if @scope.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] name Value to be assigned + def name=(name) + if name.nil? + fail ArgumentError, 'name cannot be nil' + end + + if name.to_s.length > 100 + fail ArgumentError, 'invalid value for "name", the character length must be smaller than or equal to 100.' + end + + if name.to_s.length < 1 + fail ArgumentError, 'invalid value for "name", the character length must be greater than or equal to 1.' + end + + @name = name + end + + # Custom attribute writer method with validation + # @param [Object] scope Value to be assigned + def scope=(scope) + if scope.nil? + fail ArgumentError, 'scope cannot be nil' + end + + @scope = scope + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + name == o.name && + scope == o.scope && + expires_at == o.expires_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [name, scope, expires_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/create_sandbox_session_request.rb b/lib/volcano/generated/lib/volcano-generated/models/create_sandbox_session_request.rb new file mode 100644 index 00000000..867715d2 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/create_sandbox_session_request.rb @@ -0,0 +1,305 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class CreateSandboxSessionRequest < ApiModelBase + attr_accessor :preset + + attr_accessor :sandbox_id + + attr_accessor :memory_mb + + # Region such as `us-east-1`. Region IDs issued by earlier versions of the API are still accepted. + attr_accessor :region + + attr_accessor :max_duration_seconds + + attr_accessor :idle_timeout_seconds + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'preset' => :'preset', + :'sandbox_id' => :'sandbox_id', + :'memory_mb' => :'memory_mb', + :'region' => :'region', + :'max_duration_seconds' => :'max_duration_seconds', + :'idle_timeout_seconds' => :'idle_timeout_seconds' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'preset' => :'String', + :'sandbox_id' => :'String', + :'memory_mb' => :'Integer', + :'region' => :'String', + :'max_duration_seconds' => :'Integer', + :'idle_timeout_seconds' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CreateSandboxSessionRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CreateSandboxSessionRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'preset') + self.preset = attributes[:'preset'] + end + + if attributes.key?(:'sandbox_id') + self.sandbox_id = attributes[:'sandbox_id'] + end + + if attributes.key?(:'memory_mb') + self.memory_mb = attributes[:'memory_mb'] + end + + if attributes.key?(:'region') + self.region = attributes[:'region'] + else + self.region = nil + end + + if attributes.key?(:'max_duration_seconds') + self.max_duration_seconds = attributes[:'max_duration_seconds'] + else + self.max_duration_seconds = 3600 + end + + if attributes.key?(:'idle_timeout_seconds') + self.idle_timeout_seconds = attributes[:'idle_timeout_seconds'] + else + self.idle_timeout_seconds = 0 + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @region.nil? + invalid_properties.push('invalid value for "region", region cannot be nil.') + end + + pattern = Regexp.new(/^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$/) + if @region !~ pattern + invalid_properties.push("invalid value for \"region\", must conform to the pattern #{pattern}.") + end + + if !@max_duration_seconds.nil? && @max_duration_seconds > 28800 + invalid_properties.push('invalid value for "max_duration_seconds", must be smaller than or equal to 28800.') + end + + if !@max_duration_seconds.nil? && @max_duration_seconds < 30 + invalid_properties.push('invalid value for "max_duration_seconds", must be greater than or equal to 30.') + end + + if !@idle_timeout_seconds.nil? && @idle_timeout_seconds > 28800 + invalid_properties.push('invalid value for "idle_timeout_seconds", must be smaller than or equal to 28800.') + end + + if !@idle_timeout_seconds.nil? && @idle_timeout_seconds < 0 + invalid_properties.push('invalid value for "idle_timeout_seconds", must be greater than or equal to 0.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + preset_validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + return false unless preset_validator.valid?(@preset) + memory_mb_validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + return false unless memory_mb_validator.valid?(@memory_mb) + return false if @region.nil? + return false if @region !~ Regexp.new(/^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$/) + return false if !@max_duration_seconds.nil? && @max_duration_seconds > 28800 + return false if !@max_duration_seconds.nil? && @max_duration_seconds < 30 + return false if !@idle_timeout_seconds.nil? && @idle_timeout_seconds > 28800 + return false if !@idle_timeout_seconds.nil? && @idle_timeout_seconds < 0 + true + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] preset Object to be assigned + def preset=(preset) + validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + unless validator.valid?(preset) + fail ArgumentError, "invalid value for \"preset\", must be one of #{validator.allowable_values}." + end + @preset = preset + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] memory_mb Object to be assigned + def memory_mb=(memory_mb) + validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + unless validator.valid?(memory_mb) + fail ArgumentError, "invalid value for \"memory_mb\", must be one of #{validator.allowable_values}." + end + @memory_mb = memory_mb + end + + # Custom attribute writer method with validation + # @param [Object] region Value to be assigned + def region=(region) + if region.nil? + fail ArgumentError, 'region cannot be nil' + end + + pattern = Regexp.new(/^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$/) + if region !~ pattern + fail ArgumentError, "invalid value for \"region\", must conform to the pattern #{pattern}." + end + + @region = region + end + + # Custom attribute writer method with validation + # @param [Object] max_duration_seconds Value to be assigned + def max_duration_seconds=(max_duration_seconds) + if max_duration_seconds.nil? + fail ArgumentError, 'max_duration_seconds cannot be nil' + end + + if max_duration_seconds > 28800 + fail ArgumentError, 'invalid value for "max_duration_seconds", must be smaller than or equal to 28800.' + end + + if max_duration_seconds < 30 + fail ArgumentError, 'invalid value for "max_duration_seconds", must be greater than or equal to 30.' + end + + @max_duration_seconds = max_duration_seconds + end + + # Custom attribute writer method with validation + # @param [Object] idle_timeout_seconds Value to be assigned + def idle_timeout_seconds=(idle_timeout_seconds) + if idle_timeout_seconds.nil? + fail ArgumentError, 'idle_timeout_seconds cannot be nil' + end + + if idle_timeout_seconds > 28800 + fail ArgumentError, 'invalid value for "idle_timeout_seconds", must be smaller than or equal to 28800.' + end + + if idle_timeout_seconds < 0 + fail ArgumentError, 'invalid value for "idle_timeout_seconds", must be greater than or equal to 0.' + end + + @idle_timeout_seconds = idle_timeout_seconds + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + preset == o.preset && + sandbox_id == o.sandbox_id && + memory_mb == o.memory_mb && + region == o.region && + max_duration_seconds == o.max_duration_seconds && + idle_timeout_seconds == o.idle_timeout_seconds + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [preset, sandbox_id, memory_mb, region, max_duration_seconds, idle_timeout_seconds].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/create_sandbox_template_request.rb b/lib/volcano/generated/lib/volcano-generated/models/create_sandbox_template_request.rb new file mode 100644 index 00000000..674cf1ba --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/create_sandbox_template_request.rb @@ -0,0 +1,248 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class CreateSandboxTemplateRequest < ApiModelBase + attr_accessor :name + + attr_accessor :preset + + attr_accessor :memory_mb + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'name' => :'name', + :'preset' => :'preset', + :'memory_mb' => :'memory_mb' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'name' => :'String', + :'preset' => :'String', + :'memory_mb' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CreateSandboxTemplateRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CreateSandboxTemplateRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'name') + self.name = attributes[:'name'] + else + self.name = nil + end + + if attributes.key?(:'preset') + self.preset = attributes[:'preset'] + else + self.preset = nil + end + + if attributes.key?(:'memory_mb') + self.memory_mb = attributes[:'memory_mb'] + else + self.memory_mb = MEMORY_MB::N1024 + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @name.nil? + invalid_properties.push('invalid value for "name", name cannot be nil.') + end + + pattern = Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + if @name !~ pattern + invalid_properties.push("invalid value for \"name\", must conform to the pattern #{pattern}.") + end + + if @preset.nil? + invalid_properties.push('invalid value for "preset", preset cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @name.nil? + return false if @name !~ Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + return false if @preset.nil? + preset_validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + return false unless preset_validator.valid?(@preset) + memory_mb_validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + return false unless memory_mb_validator.valid?(@memory_mb) + true + end + + # Custom attribute writer method with validation + # @param [Object] name Value to be assigned + def name=(name) + if name.nil? + fail ArgumentError, 'name cannot be nil' + end + + pattern = Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + if name !~ pattern + fail ArgumentError, "invalid value for \"name\", must conform to the pattern #{pattern}." + end + + @name = name + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] preset Object to be assigned + def preset=(preset) + validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + unless validator.valid?(preset) + fail ArgumentError, "invalid value for \"preset\", must be one of #{validator.allowable_values}." + end + @preset = preset + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] memory_mb Object to be assigned + def memory_mb=(memory_mb) + validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + unless validator.valid?(memory_mb) + fail ArgumentError, "invalid value for \"memory_mb\", must be one of #{validator.allowable_values}." + end + @memory_mb = memory_mb + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + name == o.name && + preset == o.preset && + memory_mb == o.memory_mb + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [name, preset, memory_mb].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/create_variable_request.rb b/lib/volcano/generated/lib/volcano-generated/models/create_variable_request.rb index 9a3bed07..83e50874 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/create_variable_request.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/create_variable_request.rb @@ -18,6 +18,7 @@ class CreateVariableRequest < ApiModelBase # Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable. attr_accessor :shared + # Project variable name. Function runtime names such as AWS_REGION are reserved and return 400; see the environment variables guide for the full list. attr_accessor :name attr_accessor :value diff --git a/lib/volcano/generated/lib/volcano-generated/models/created_project_access_token.rb b/lib/volcano/generated/lib/volcano-generated/models/created_project_access_token.rb new file mode 100644 index 00000000..13e3cae1 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/created_project_access_token.rb @@ -0,0 +1,459 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class CreatedProjectAccessToken < ApiModelBase + attr_accessor :id + + attr_accessor :project_id + + # Unique per project. + attr_accessor :name + + # First 12 characters of the secret, for recognising a token in a list. + attr_accessor :token_prefix + + attr_accessor :scope + + # `revoked` means the token was deliberately revoked, by you or by the deletion of its project. `expired` means it simply reached `expires_at`; nothing was taken away. Both are refused, and both keep their record so a token's name, prefix, last use, and request history remain available after a leak. A token revoked before its expiry passed stays `revoked`, because that is the fact worth keeping. + attr_accessor :status + + # What created the token. + attr_accessor :token_source + + # Absent for a token that does not expire. + attr_accessor :expires_at + + # Updated at most once every few minutes, so it may lag slightly. + attr_accessor :last_used_at + + attr_accessor :created_at + + # Requests authenticated with this token since it was created. + attr_accessor :all_time_requests + + # The secret. Returned only here, and not recoverable afterwards: the server stores a hash rather than the value. Save it now. + attr_accessor :token + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'project_id' => :'project_id', + :'name' => :'name', + :'token_prefix' => :'token_prefix', + :'scope' => :'scope', + :'status' => :'status', + :'token_source' => :'token_source', + :'expires_at' => :'expires_at', + :'last_used_at' => :'last_used_at', + :'created_at' => :'created_at', + :'all_time_requests' => :'all_time_requests', + :'token' => :'token' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'project_id' => :'String', + :'name' => :'String', + :'token_prefix' => :'String', + :'scope' => :'ProjectAccessTokenScope', + :'status' => :'String', + :'token_source' => :'String', + :'expires_at' => :'Time', + :'last_used_at' => :'Time', + :'created_at' => :'Time', + :'all_time_requests' => :'Integer', + :'token' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + :'expires_at', + :'last_used_at', + ]) + end + + # List of class defined in allOf (OpenAPI v3) + def self.openapi_all_of + [ + :'ProjectAccessToken' + ] + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::CreatedProjectAccessToken` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::CreatedProjectAccessToken`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'project_id') + self.project_id = attributes[:'project_id'] + else + self.project_id = nil + end + + if attributes.key?(:'name') + self.name = attributes[:'name'] + else + self.name = nil + end + + if attributes.key?(:'token_prefix') + self.token_prefix = attributes[:'token_prefix'] + else + self.token_prefix = nil + end + + if attributes.key?(:'scope') + self.scope = attributes[:'scope'] + else + self.scope = nil + end + + if attributes.key?(:'status') + self.status = attributes[:'status'] + else + self.status = nil + end + + if attributes.key?(:'token_source') + self.token_source = attributes[:'token_source'] + else + self.token_source = nil + end + + if attributes.key?(:'expires_at') + self.expires_at = attributes[:'expires_at'] + end + + if attributes.key?(:'last_used_at') + self.last_used_at = attributes[:'last_used_at'] + end + + if attributes.key?(:'created_at') + self.created_at = attributes[:'created_at'] + else + self.created_at = nil + end + + if attributes.key?(:'all_time_requests') + self.all_time_requests = attributes[:'all_time_requests'] + else + self.all_time_requests = nil + end + + if attributes.key?(:'token') + self.token = attributes[:'token'] + else + self.token = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @project_id.nil? + invalid_properties.push('invalid value for "project_id", project_id cannot be nil.') + end + + if @name.nil? + invalid_properties.push('invalid value for "name", name cannot be nil.') + end + + if @token_prefix.nil? + invalid_properties.push('invalid value for "token_prefix", token_prefix cannot be nil.') + end + + if @scope.nil? + invalid_properties.push('invalid value for "scope", scope cannot be nil.') + end + + if @status.nil? + invalid_properties.push('invalid value for "status", status cannot be nil.') + end + + if @token_source.nil? + invalid_properties.push('invalid value for "token_source", token_source cannot be nil.') + end + + if @created_at.nil? + invalid_properties.push('invalid value for "created_at", created_at cannot be nil.') + end + + if @all_time_requests.nil? + invalid_properties.push('invalid value for "all_time_requests", all_time_requests cannot be nil.') + end + + if @token.nil? + invalid_properties.push('invalid value for "token", token cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @project_id.nil? + return false if @name.nil? + return false if @token_prefix.nil? + return false if @scope.nil? + return false if @status.nil? + status_validator = EnumAttributeValidator.new('String', ["active", "revoked", "expired"]) + return false unless status_validator.valid?(@status) + return false if @token_source.nil? + token_source_validator = EnumAttributeValidator.new('String', ["api", "cli", "dashboard"]) + return false unless token_source_validator.valid?(@token_source) + return false if @created_at.nil? + return false if @all_time_requests.nil? + return false if @token.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method with validation + # @param [Object] project_id Value to be assigned + def project_id=(project_id) + if project_id.nil? + fail ArgumentError, 'project_id cannot be nil' + end + + @project_id = project_id + end + + # Custom attribute writer method with validation + # @param [Object] name Value to be assigned + def name=(name) + if name.nil? + fail ArgumentError, 'name cannot be nil' + end + + @name = name + end + + # Custom attribute writer method with validation + # @param [Object] token_prefix Value to be assigned + def token_prefix=(token_prefix) + if token_prefix.nil? + fail ArgumentError, 'token_prefix cannot be nil' + end + + @token_prefix = token_prefix + end + + # Custom attribute writer method with validation + # @param [Object] scope Value to be assigned + def scope=(scope) + if scope.nil? + fail ArgumentError, 'scope cannot be nil' + end + + @scope = scope + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] status Object to be assigned + def status=(status) + validator = EnumAttributeValidator.new('String', ["active", "revoked", "expired"]) + unless validator.valid?(status) + fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}." + end + @status = status + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] token_source Object to be assigned + def token_source=(token_source) + validator = EnumAttributeValidator.new('String', ["api", "cli", "dashboard"]) + unless validator.valid?(token_source) + fail ArgumentError, "invalid value for \"token_source\", must be one of #{validator.allowable_values}." + end + @token_source = token_source + end + + # Custom attribute writer method with validation + # @param [Object] created_at Value to be assigned + def created_at=(created_at) + if created_at.nil? + fail ArgumentError, 'created_at cannot be nil' + end + + @created_at = created_at + end + + # Custom attribute writer method with validation + # @param [Object] all_time_requests Value to be assigned + def all_time_requests=(all_time_requests) + if all_time_requests.nil? + fail ArgumentError, 'all_time_requests cannot be nil' + end + + @all_time_requests = all_time_requests + end + + # Custom attribute writer method with validation + # @param [Object] token Value to be assigned + def token=(token) + if token.nil? + fail ArgumentError, 'token cannot be nil' + end + + @token = token + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + project_id == o.project_id && + name == o.name && + token_prefix == o.token_prefix && + scope == o.scope && + status == o.status && + token_source == o.token_source && + expires_at == o.expires_at && + last_used_at == o.last_used_at && + created_at == o.created_at && + all_time_requests == o.all_time_requests && + token == o.token + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, project_id, name, token_prefix, scope, status, token_source, expires_at, last_used_at, created_at, all_time_requests, token].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/database_query_performance_item.rb b/lib/volcano/generated/lib/volcano-generated/models/database_query_performance_item.rb index 550bcacd..0391e758 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/database_query_performance_item.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/database_query_performance_item.rb @@ -18,12 +18,12 @@ class DatabaseQueryPerformanceItem < ApiModelBase # pg_stat_statements query identifier. attr_accessor :query_id - # Normalized and obfuscated representative query text. + # Normalized representative query text with literal values replaced by `?`. attr_accessor :query attr_accessor :database - # Database role used for the query. + # Postgres role that ran the query, such as `anon` or `authenticated` for RLS-enforced connections, `service_role`, the database owner role for full-access connections, or a role you created. `unknown` when the role no longer exists. attr_accessor :role attr_accessor :calls diff --git a/lib/volcano/generated/lib/volcano-generated/models/durable_execution_invocation.rb b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_invocation.rb new file mode 100644 index 00000000..0d217d75 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_invocation.rb @@ -0,0 +1,191 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # A window in which the function's code was running. + class DurableExecutionInvocation < ApiModelBase + attr_accessor :started_at + + attr_accessor :ended_at + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'started_at' => :'started_at', + :'ended_at' => :'ended_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'started_at' => :'Time', + :'ended_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::DurableExecutionInvocation` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::DurableExecutionInvocation`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'started_at') + self.started_at = attributes[:'started_at'] + else + self.started_at = nil + end + + if attributes.key?(:'ended_at') + self.ended_at = attributes[:'ended_at'] + else + self.ended_at = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @started_at.nil? + invalid_properties.push('invalid value for "started_at", started_at cannot be nil.') + end + + if @ended_at.nil? + invalid_properties.push('invalid value for "ended_at", ended_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @started_at.nil? + return false if @ended_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] started_at Value to be assigned + def started_at=(started_at) + if started_at.nil? + fail ArgumentError, 'started_at cannot be nil' + end + + @started_at = started_at + end + + # Custom attribute writer method with validation + # @param [Object] ended_at Value to be assigned + def ended_at=(ended_at) + if ended_at.nil? + fail ArgumentError, 'ended_at cannot be nil' + end + + @ended_at = ended_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + started_at == o.started_at && + ended_at == o.ended_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [started_at, ended_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation.rb b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation.rb new file mode 100644 index 00000000..f869c497 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation.rb @@ -0,0 +1,372 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # One operation on an execution's timeline. + class DurableExecutionOperation < ApiModelBase + # Identifies the operation within its execution. + attr_accessor :id + + # The operation this one ran inside: a child context, map item or parallel branch, or the execution itself for top-level work. Absent only on the execution. + attr_accessor :parent_id + + # The name the handler gave the operation. Map items and parallel branches the handler did not name carry the SDK's positional name, such as `map-item-0`. Absent for an unnamed operation. + attr_accessor :name + + # The kind of checkpointed operation Volcano recorded. + attr_accessor :type + + # The operation as the handler wrote it: `ctx.step` is `step`, `ctx.wait` is `wait`, `ctx.waitUntil` is `wait_until`, `ctx.child` is `child`, `ctx.map` is `map` with one `map_item` per item, and `ctx.parallel` is `parallel` with one `parallel_branch` per branch. + attr_accessor :kind + + # Where the operation stands. `waiting` holds no runtime: a wait that has not elapsed, or a `waitUntil` between checks. `retrying` is a step whose last attempt failed and whose next one is scheduled at `next_attempt_at`. Work still open when the execution ended is `cancelled` at the moment it ended. `unknown` is only ever the execution itself, when its outcome was lost with its history, as in the execution's own `unknown` status. + attr_accessor :status + + attr_accessor :started_at + + # Present once the operation has ended. + attr_accessor :ended_at + + # When a wait is due to elapse. + attr_accessor :scheduled_end_at + + # When a step's next attempt, or a `waitUntil`'s next check, is due. Present only while one is scheduled. + attr_accessor :next_attempt_at + + # Each run of a step's body, in order. Present on steps and `waitUntil` polls, where each check is an attempt. + attr_accessor :attempts + + attr_accessor :error + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'parent_id' => :'parent_id', + :'name' => :'name', + :'type' => :'type', + :'kind' => :'kind', + :'status' => :'status', + :'started_at' => :'started_at', + :'ended_at' => :'ended_at', + :'scheduled_end_at' => :'scheduled_end_at', + :'next_attempt_at' => :'next_attempt_at', + :'attempts' => :'attempts', + :'error' => :'error' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'parent_id' => :'String', + :'name' => :'String', + :'type' => :'String', + :'kind' => :'String', + :'status' => :'String', + :'started_at' => :'Time', + :'ended_at' => :'Time', + :'scheduled_end_at' => :'Time', + :'next_attempt_at' => :'Time', + :'attempts' => :'Array', + :'error' => :'DurableExecutionError' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::DurableExecutionOperation` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::DurableExecutionOperation`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'parent_id') + self.parent_id = attributes[:'parent_id'] + end + + if attributes.key?(:'name') + self.name = attributes[:'name'] + end + + if attributes.key?(:'type') + self.type = attributes[:'type'] + else + self.type = nil + end + + if attributes.key?(:'kind') + self.kind = attributes[:'kind'] + else + self.kind = nil + end + + if attributes.key?(:'status') + self.status = attributes[:'status'] + else + self.status = nil + end + + if attributes.key?(:'started_at') + self.started_at = attributes[:'started_at'] + else + self.started_at = nil + end + + if attributes.key?(:'ended_at') + self.ended_at = attributes[:'ended_at'] + end + + if attributes.key?(:'scheduled_end_at') + self.scheduled_end_at = attributes[:'scheduled_end_at'] + end + + if attributes.key?(:'next_attempt_at') + self.next_attempt_at = attributes[:'next_attempt_at'] + end + + if attributes.key?(:'attempts') + if (value = attributes[:'attempts']).is_a?(Array) + self.attempts = value + end + end + + if attributes.key?(:'error') + self.error = attributes[:'error'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @type.nil? + invalid_properties.push('invalid value for "type", type cannot be nil.') + end + + if @kind.nil? + invalid_properties.push('invalid value for "kind", kind cannot be nil.') + end + + if @status.nil? + invalid_properties.push('invalid value for "status", status cannot be nil.') + end + + if @started_at.nil? + invalid_properties.push('invalid value for "started_at", started_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @type.nil? + type_validator = EnumAttributeValidator.new('String', ["execution", "step", "wait", "callback", "context", "chained_invoke"]) + return false unless type_validator.valid?(@type) + return false if @kind.nil? + kind_validator = EnumAttributeValidator.new('String', ["execution", "step", "wait", "wait_until", "callback", "child", "map", "map_item", "parallel", "parallel_branch", "invoke"]) + return false unless kind_validator.valid?(@kind) + return false if @status.nil? + status_validator = EnumAttributeValidator.new('String', ["running", "waiting", "retrying", "succeeded", "failed", "cancelled", "timed_out", "stopped", "unknown"]) + return false unless status_validator.valid?(@status) + return false if @started_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] type Object to be assigned + def type=(type) + validator = EnumAttributeValidator.new('String', ["execution", "step", "wait", "callback", "context", "chained_invoke"]) + unless validator.valid?(type) + fail ArgumentError, "invalid value for \"type\", must be one of #{validator.allowable_values}." + end + @type = type + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] kind Object to be assigned + def kind=(kind) + validator = EnumAttributeValidator.new('String', ["execution", "step", "wait", "wait_until", "callback", "child", "map", "map_item", "parallel", "parallel_branch", "invoke"]) + unless validator.valid?(kind) + fail ArgumentError, "invalid value for \"kind\", must be one of #{validator.allowable_values}." + end + @kind = kind + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] status Object to be assigned + def status=(status) + validator = EnumAttributeValidator.new('String', ["running", "waiting", "retrying", "succeeded", "failed", "cancelled", "timed_out", "stopped", "unknown"]) + unless validator.valid?(status) + fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}." + end + @status = status + end + + # Custom attribute writer method with validation + # @param [Object] started_at Value to be assigned + def started_at=(started_at) + if started_at.nil? + fail ArgumentError, 'started_at cannot be nil' + end + + @started_at = started_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + parent_id == o.parent_id && + name == o.name && + type == o.type && + kind == o.kind && + status == o.status && + started_at == o.started_at && + ended_at == o.ended_at && + scheduled_end_at == o.scheduled_end_at && + next_attempt_at == o.next_attempt_at && + attempts == o.attempts && + error == o.error + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, parent_id, name, type, kind, status, started_at, ended_at, scheduled_end_at, next_attempt_at, attempts, error].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_attempt.rb b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_attempt.rb new file mode 100644 index 00000000..327f642c --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_attempt.rb @@ -0,0 +1,271 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # One run of a step's body. + class DurableExecutionOperationAttempt < ApiModelBase + # The attempt's number, starting at 1. + attr_accessor :attempt + + # How the attempt ended. A `waitUntil` check whose condition did not hold yet is `succeeded`: the check ran, and the poll continues. + attr_accessor :status + + attr_accessor :started_at + + # Present once the attempt has ended. + attr_accessor :ended_at + + attr_accessor :error + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'attempt' => :'attempt', + :'status' => :'status', + :'started_at' => :'started_at', + :'ended_at' => :'ended_at', + :'error' => :'error' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'attempt' => :'Integer', + :'status' => :'String', + :'started_at' => :'Time', + :'ended_at' => :'Time', + :'error' => :'DurableExecutionError' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::DurableExecutionOperationAttempt` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::DurableExecutionOperationAttempt`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'attempt') + self.attempt = attributes[:'attempt'] + else + self.attempt = nil + end + + if attributes.key?(:'status') + self.status = attributes[:'status'] + else + self.status = nil + end + + if attributes.key?(:'started_at') + self.started_at = attributes[:'started_at'] + else + self.started_at = nil + end + + if attributes.key?(:'ended_at') + self.ended_at = attributes[:'ended_at'] + end + + if attributes.key?(:'error') + self.error = attributes[:'error'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @attempt.nil? + invalid_properties.push('invalid value for "attempt", attempt cannot be nil.') + end + + if @attempt < 1 + invalid_properties.push('invalid value for "attempt", must be greater than or equal to 1.') + end + + if @status.nil? + invalid_properties.push('invalid value for "status", status cannot be nil.') + end + + if @started_at.nil? + invalid_properties.push('invalid value for "started_at", started_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @attempt.nil? + return false if @attempt < 1 + return false if @status.nil? + status_validator = EnumAttributeValidator.new('String', ["running", "succeeded", "failed"]) + return false unless status_validator.valid?(@status) + return false if @started_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] attempt Value to be assigned + def attempt=(attempt) + if attempt.nil? + fail ArgumentError, 'attempt cannot be nil' + end + + if attempt < 1 + fail ArgumentError, 'invalid value for "attempt", must be greater than or equal to 1.' + end + + @attempt = attempt + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] status Object to be assigned + def status=(status) + validator = EnumAttributeValidator.new('String', ["running", "succeeded", "failed"]) + unless validator.valid?(status) + fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}." + end + @status = status + end + + # Custom attribute writer method with validation + # @param [Object] started_at Value to be assigned + def started_at=(started_at) + if started_at.nil? + fail ArgumentError, 'started_at cannot be nil' + end + + @started_at = started_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + attempt == o.attempt && + status == o.status && + started_at == o.started_at && + ended_at == o.ended_at && + error == o.error + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [attempt, status, started_at, ended_at, error].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_list.rb b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_list.rb new file mode 100644 index 00000000..3eb3cf8f --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/durable_execution_operation_list.rb @@ -0,0 +1,234 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # A durable execution's trace. + class DurableExecutionOperationList < ApiModelBase + # Every operation the execution began. The execution itself comes first and is the only operation without a `parent_id`; the rest follow in the order they started. + attr_accessor :data + + # When the function's code was running, oldest first. An execution suspended in a wait holds no runtime, so the gaps between these are not charged as compute. + attr_accessor :invocations + + # `true` once the execution has finished and nothing more will be recorded. Its operations no longer change, and it is no longer refreshed on read; a final invocation window can still be added shortly after. + attr_accessor :complete + + # When the trace was last refreshed. Absent before it has been refreshed at all. A running execution's trace is usually within about ten seconds of the execution, and further behind when many executions are being watched at once. + attr_accessor :synced_at + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data', + :'invocations' => :'invocations', + :'complete' => :'complete', + :'synced_at' => :'synced_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array', + :'invocations' => :'Array', + :'complete' => :'Boolean', + :'synced_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::DurableExecutionOperationList` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::DurableExecutionOperationList`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + + if attributes.key?(:'invocations') + if (value = attributes[:'invocations']).is_a?(Array) + self.invocations = value + end + else + self.invocations = nil + end + + if attributes.key?(:'complete') + self.complete = attributes[:'complete'] + else + self.complete = nil + end + + if attributes.key?(:'synced_at') + self.synced_at = attributes[:'synced_at'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + if @invocations.nil? + invalid_properties.push('invalid value for "invocations", invocations cannot be nil.') + end + + if @complete.nil? + invalid_properties.push('invalid value for "complete", complete cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + return false if @invocations.nil? + return false if @complete.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Custom attribute writer method with validation + # @param [Object] invocations Value to be assigned + def invocations=(invocations) + if invocations.nil? + fail ArgumentError, 'invocations cannot be nil' + end + + @invocations = invocations + end + + # Custom attribute writer method with validation + # @param [Object] complete Value to be assigned + def complete=(complete) + if complete.nil? + fail ArgumentError, 'complete cannot be nil' + end + + @complete = complete + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data && + invocations == o.invocations && + complete == o.complete && + synced_at == o.synced_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data, invocations, complete, synced_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/frontend.rb b/lib/volcano/generated/lib/volcano-generated/models/frontend.rb index 69025e69..5e9b86c6 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/frontend.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/frontend.rb @@ -15,6 +15,12 @@ module Volcano::Generated class Frontend < ApiModelBase + # All preserves access to all project variables. Shared includes the project frontend shared-variable list. Scoped includes only explicitly declared variables in builds and runtime. Omission preserves the stored selection. + attr_accessor :variable_scope + + # Names selected when variable_scope is scoped. Missing declared values reject deployment. Omission preserves the stored list; an empty list clears it. + attr_accessor :declared_variables + attr_accessor :id attr_accessor :project_id @@ -79,6 +85,8 @@ def valid?(value) # Attribute mapping from ruby-style variable name to JSON key. def self.attribute_map { + :'variable_scope' => :'variable_scope', + :'declared_variables' => :'declared_variables', :'id' => :'id', :'project_id' => :'project_id', :'name' => :'name', @@ -111,6 +119,8 @@ def self.acceptable_attributes # Attribute type mapping. def self.openapi_types { + :'variable_scope' => :'String', + :'declared_variables' => :'Array', :'id' => :'String', :'project_id' => :'String', :'name' => :'String', @@ -152,6 +162,16 @@ def initialize(attributes = {}) h[k.to_sym] = v } + if attributes.key?(:'variable_scope') + self.variable_scope = attributes[:'variable_scope'] + end + + if attributes.key?(:'declared_variables') + if (value = attributes[:'declared_variables']).is_a?(Array) + self.declared_variables = value + end + end + if attributes.key?(:'id') self.id = attributes[:'id'] else @@ -292,6 +312,8 @@ def list_invalid_properties # @return true if the model is valid def valid? warn '[DEPRECATED] the `valid?` method is obsolete' + variable_scope_validator = EnumAttributeValidator.new('String', ["all", "shared", "scoped"]) + return false unless variable_scope_validator.valid?(@variable_scope) return false if @id.nil? return false if @project_id.nil? return false if @name.nil? @@ -312,6 +334,26 @@ def valid? true end + # Custom attribute writer method checking allowed values (enum). + # @param [Object] variable_scope Object to be assigned + def variable_scope=(variable_scope) + validator = EnumAttributeValidator.new('String', ["all", "shared", "scoped"]) + unless validator.valid?(variable_scope) + fail ArgumentError, "invalid value for \"variable_scope\", must be one of #{validator.allowable_values}." + end + @variable_scope = variable_scope + end + + # Custom attribute writer method with validation + # @param [Object] declared_variables Value to be assigned + def declared_variables=(declared_variables) + if declared_variables.nil? + fail ArgumentError, 'declared_variables cannot be nil' + end + + @declared_variables = declared_variables + end + # Custom attribute writer method with validation # @param [Object] id Value to be assigned def id=(id) @@ -430,6 +472,8 @@ def updated_at=(updated_at) def ==(o) return true if self.equal?(o) self.class == o.class && + variable_scope == o.variable_scope && + declared_variables == o.declared_variables && id == o.id && project_id == o.project_id && name == o.name && @@ -457,7 +501,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [id, project_id, name, framework, app_root, status, provisioning_started_at, deployed_regions, current_deployment_id, pending_deployment_id, site_url, custom_domain, custom_domain_status, last_invoked_at, created_at, updated_at].hash + [variable_scope, declared_variables, id, project_id, name, framework, app_root, status, provisioning_started_at, deployed_regions, current_deployment_id, pending_deployment_id, site_url, custom_domain, custom_domain_status, last_invoked_at, created_at, updated_at].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/frontend_custom_domain_response.rb b/lib/volcano/generated/lib/volcano-generated/models/frontend_custom_domain_response.rb index e58e1c30..14a93b92 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/frontend_custom_domain_response.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/frontend_custom_domain_response.rb @@ -27,6 +27,9 @@ class FrontendCustomDomainResponse < ApiModelBase attr_accessor :required_routing_record + # DNS routing target hostname for this frontend. The DNS record type depends on whether the custom domain is a zone apex. + attr_accessor :routing_target_hostname + attr_accessor :effective_urls attr_accessor :created_at @@ -64,6 +67,7 @@ def self.attribute_map :'verification_status' => :'verification_status', :'verification_records' => :'verification_records', :'required_routing_record' => :'required_routing_record', + :'routing_target_hostname' => :'routing_target_hostname', :'effective_urls' => :'effective_urls', :'created_at' => :'created_at', :'updated_at' => :'updated_at' @@ -89,6 +93,7 @@ def self.openapi_types :'verification_status' => :'String', :'verification_records' => :'Array', :'required_routing_record' => :'FrontendDomainRoutingRecord', + :'routing_target_hostname' => :'String', :'effective_urls' => :'Array', :'created_at' => :'Time', :'updated_at' => :'Time' @@ -151,6 +156,10 @@ def initialize(attributes = {}) self.required_routing_record = attributes[:'required_routing_record'] end + if attributes.key?(:'routing_target_hostname') + self.routing_target_hostname = attributes[:'routing_target_hostname'] + end + if attributes.key?(:'effective_urls') if (value = attributes[:'effective_urls']).is_a?(Array) self.effective_urls = value @@ -309,6 +318,7 @@ def ==(o) verification_status == o.verification_status && verification_records == o.verification_records && required_routing_record == o.required_routing_record && + routing_target_hostname == o.routing_target_hostname && effective_urls == o.effective_urls && created_at == o.created_at && updated_at == o.updated_at @@ -323,7 +333,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [domain, tls_mode, domain_status, verification_status, verification_records, required_routing_record, effective_urls, created_at, updated_at].hash + [domain, tls_mode, domain_status, verification_status, verification_records, required_routing_record, routing_target_hostname, effective_urls, created_at, updated_at].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/frontend_deployment.rb b/lib/volcano/generated/lib/volcano-generated/models/frontend_deployment.rb index f58b9557..1023a6c7 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/frontend_deployment.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/frontend_deployment.rb @@ -32,25 +32,16 @@ class FrontendDeployment < ApiModelBase # Platform user that triggered a request-initiated deployment; absent for git and system deployments. attr_accessor :initiated_by - attr_accessor :artifact_bucket - - attr_accessor :artifact_key - - attr_accessor :artifact_version - attr_accessor :site_url - attr_accessor :cloudformation_stack_id - - attr_accessor :cloudformation_stack_url + # Total build time recorded for this deployment, in seconds. + attr_accessor :build_duration_seconds - # Total CodeBuild build duration recorded for this deployment, in seconds. - attr_accessor :codebuild_duration_seconds + # Number of completed builds included in build_duration_seconds. + attr_accessor :build_count - # Number of completed CodeBuild builds included in codebuild_duration_seconds. - attr_accessor :codebuild_build_count - - attr_accessor :codebuild_duration_recorded_at + # When the build time was last recorded. + attr_accessor :build_duration_recorded_at attr_accessor :progress @@ -92,15 +83,10 @@ def self.attribute_map :'status' => :'status', :'deploy_source' => :'deploy_source', :'initiated_by' => :'initiated_by', - :'artifact_bucket' => :'artifact_bucket', - :'artifact_key' => :'artifact_key', - :'artifact_version' => :'artifact_version', :'site_url' => :'site_url', - :'cloudformation_stack_id' => :'cloudformation_stack_id', - :'cloudformation_stack_url' => :'cloudformation_stack_url', - :'codebuild_duration_seconds' => :'codebuild_duration_seconds', - :'codebuild_build_count' => :'codebuild_build_count', - :'codebuild_duration_recorded_at' => :'codebuild_duration_recorded_at', + :'build_duration_seconds' => :'build_duration_seconds', + :'build_count' => :'build_count', + :'build_duration_recorded_at' => :'build_duration_recorded_at', :'progress' => :'progress', :'error_message' => :'error_message', :'created_at' => :'created_at', @@ -128,15 +114,10 @@ def self.openapi_types :'status' => :'String', :'deploy_source' => :'String', :'initiated_by' => :'String', - :'artifact_bucket' => :'String', - :'artifact_key' => :'String', - :'artifact_version' => :'String', :'site_url' => :'String', - :'cloudformation_stack_id' => :'String', - :'cloudformation_stack_url' => :'String', - :'codebuild_duration_seconds' => :'Integer', - :'codebuild_build_count' => :'Integer', - :'codebuild_duration_recorded_at' => :'Time', + :'build_duration_seconds' => :'Integer', + :'build_count' => :'Integer', + :'build_duration_recorded_at' => :'Time', :'progress' => :'DeploymentProgress', :'error_message' => :'String', :'created_at' => :'Time', @@ -206,40 +187,20 @@ def initialize(attributes = {}) self.initiated_by = attributes[:'initiated_by'] end - if attributes.key?(:'artifact_bucket') - self.artifact_bucket = attributes[:'artifact_bucket'] - end - - if attributes.key?(:'artifact_key') - self.artifact_key = attributes[:'artifact_key'] - end - - if attributes.key?(:'artifact_version') - self.artifact_version = attributes[:'artifact_version'] - end - if attributes.key?(:'site_url') self.site_url = attributes[:'site_url'] end - if attributes.key?(:'cloudformation_stack_id') - self.cloudformation_stack_id = attributes[:'cloudformation_stack_id'] - end - - if attributes.key?(:'cloudformation_stack_url') - self.cloudformation_stack_url = attributes[:'cloudformation_stack_url'] - end - - if attributes.key?(:'codebuild_duration_seconds') - self.codebuild_duration_seconds = attributes[:'codebuild_duration_seconds'] + if attributes.key?(:'build_duration_seconds') + self.build_duration_seconds = attributes[:'build_duration_seconds'] end - if attributes.key?(:'codebuild_build_count') - self.codebuild_build_count = attributes[:'codebuild_build_count'] + if attributes.key?(:'build_count') + self.build_count = attributes[:'build_count'] end - if attributes.key?(:'codebuild_duration_recorded_at') - self.codebuild_duration_recorded_at = attributes[:'codebuild_duration_recorded_at'] + if attributes.key?(:'build_duration_recorded_at') + self.build_duration_recorded_at = attributes[:'build_duration_recorded_at'] end if attributes.key?(:'progress') @@ -416,15 +377,10 @@ def ==(o) status == o.status && deploy_source == o.deploy_source && initiated_by == o.initiated_by && - artifact_bucket == o.artifact_bucket && - artifact_key == o.artifact_key && - artifact_version == o.artifact_version && site_url == o.site_url && - cloudformation_stack_id == o.cloudformation_stack_id && - cloudformation_stack_url == o.cloudformation_stack_url && - codebuild_duration_seconds == o.codebuild_duration_seconds && - codebuild_build_count == o.codebuild_build_count && - codebuild_duration_recorded_at == o.codebuild_duration_recorded_at && + build_duration_seconds == o.build_duration_seconds && + build_count == o.build_count && + build_duration_recorded_at == o.build_duration_recorded_at && progress == o.progress && error_message == o.error_message && created_at == o.created_at && @@ -440,7 +396,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [id, frontend_id, project_id, operation, status, deploy_source, initiated_by, artifact_bucket, artifact_key, artifact_version, site_url, cloudformation_stack_id, cloudformation_stack_url, codebuild_duration_seconds, codebuild_build_count, codebuild_duration_recorded_at, progress, error_message, created_at, updated_at].hash + [id, frontend_id, project_id, operation, status, deploy_source, initiated_by, site_url, build_duration_seconds, build_count, build_duration_recorded_at, progress, error_message, created_at, updated_at].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/frontend_function_route.rb b/lib/volcano/generated/lib/volcano-generated/models/frontend_function_route.rb new file mode 100644 index 00000000..7f6a676e --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/frontend_function_route.rb @@ -0,0 +1,375 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class FrontendFunctionRoute < ApiModelBase + attr_accessor :id + + attr_accessor :project_id + + attr_accessor :frontend_id + + attr_accessor :function_id + + attr_accessor :path_prefix + + attr_accessor :strip_prefix + + attr_accessor :created_at + + attr_accessor :updated_at + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'project_id' => :'project_id', + :'frontend_id' => :'frontend_id', + :'function_id' => :'function_id', + :'path_prefix' => :'path_prefix', + :'strip_prefix' => :'strip_prefix', + :'created_at' => :'created_at', + :'updated_at' => :'updated_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'project_id' => :'String', + :'frontend_id' => :'String', + :'function_id' => :'String', + :'path_prefix' => :'String', + :'strip_prefix' => :'Boolean', + :'created_at' => :'Time', + :'updated_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::FrontendFunctionRoute` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::FrontendFunctionRoute`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'project_id') + self.project_id = attributes[:'project_id'] + else + self.project_id = nil + end + + if attributes.key?(:'frontend_id') + self.frontend_id = attributes[:'frontend_id'] + else + self.frontend_id = nil + end + + if attributes.key?(:'function_id') + self.function_id = attributes[:'function_id'] + else + self.function_id = nil + end + + if attributes.key?(:'path_prefix') + self.path_prefix = attributes[:'path_prefix'] + else + self.path_prefix = nil + end + + if attributes.key?(:'strip_prefix') + self.strip_prefix = attributes[:'strip_prefix'] + else + self.strip_prefix = nil + end + + if attributes.key?(:'created_at') + self.created_at = attributes[:'created_at'] + else + self.created_at = nil + end + + if attributes.key?(:'updated_at') + self.updated_at = attributes[:'updated_at'] + else + self.updated_at = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @project_id.nil? + invalid_properties.push('invalid value for "project_id", project_id cannot be nil.') + end + + if @frontend_id.nil? + invalid_properties.push('invalid value for "frontend_id", frontend_id cannot be nil.') + end + + if @function_id.nil? + invalid_properties.push('invalid value for "function_id", function_id cannot be nil.') + end + + if @path_prefix.nil? + invalid_properties.push('invalid value for "path_prefix", path_prefix cannot be nil.') + end + + if @path_prefix.to_s.length > 512 + invalid_properties.push('invalid value for "path_prefix", the character length must be smaller than or equal to 512.') + end + + if @path_prefix.to_s.length < 2 + invalid_properties.push('invalid value for "path_prefix", the character length must be greater than or equal to 2.') + end + + pattern = Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + if @path_prefix !~ pattern + invalid_properties.push("invalid value for \"path_prefix\", must conform to the pattern #{pattern}.") + end + + if @strip_prefix.nil? + invalid_properties.push('invalid value for "strip_prefix", strip_prefix cannot be nil.') + end + + if @created_at.nil? + invalid_properties.push('invalid value for "created_at", created_at cannot be nil.') + end + + if @updated_at.nil? + invalid_properties.push('invalid value for "updated_at", updated_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @project_id.nil? + return false if @frontend_id.nil? + return false if @function_id.nil? + return false if @path_prefix.nil? + return false if @path_prefix.to_s.length > 512 + return false if @path_prefix.to_s.length < 2 + return false if @path_prefix !~ Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + return false if @strip_prefix.nil? + return false if @created_at.nil? + return false if @updated_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method with validation + # @param [Object] project_id Value to be assigned + def project_id=(project_id) + if project_id.nil? + fail ArgumentError, 'project_id cannot be nil' + end + + @project_id = project_id + end + + # Custom attribute writer method with validation + # @param [Object] frontend_id Value to be assigned + def frontend_id=(frontend_id) + if frontend_id.nil? + fail ArgumentError, 'frontend_id cannot be nil' + end + + @frontend_id = frontend_id + end + + # Custom attribute writer method with validation + # @param [Object] function_id Value to be assigned + def function_id=(function_id) + if function_id.nil? + fail ArgumentError, 'function_id cannot be nil' + end + + @function_id = function_id + end + + # Custom attribute writer method with validation + # @param [Object] path_prefix Value to be assigned + def path_prefix=(path_prefix) + if path_prefix.nil? + fail ArgumentError, 'path_prefix cannot be nil' + end + + if path_prefix.to_s.length > 512 + fail ArgumentError, 'invalid value for "path_prefix", the character length must be smaller than or equal to 512.' + end + + if path_prefix.to_s.length < 2 + fail ArgumentError, 'invalid value for "path_prefix", the character length must be greater than or equal to 2.' + end + + pattern = Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + if path_prefix !~ pattern + fail ArgumentError, "invalid value for \"path_prefix\", must conform to the pattern #{pattern}." + end + + @path_prefix = path_prefix + end + + # Custom attribute writer method with validation + # @param [Object] strip_prefix Value to be assigned + def strip_prefix=(strip_prefix) + if strip_prefix.nil? + fail ArgumentError, 'strip_prefix cannot be nil' + end + + @strip_prefix = strip_prefix + end + + # Custom attribute writer method with validation + # @param [Object] created_at Value to be assigned + def created_at=(created_at) + if created_at.nil? + fail ArgumentError, 'created_at cannot be nil' + end + + @created_at = created_at + end + + # Custom attribute writer method with validation + # @param [Object] updated_at Value to be assigned + def updated_at=(updated_at) + if updated_at.nil? + fail ArgumentError, 'updated_at cannot be nil' + end + + @updated_at = updated_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + project_id == o.project_id && + frontend_id == o.frontend_id && + function_id == o.function_id && + path_prefix == o.path_prefix && + strip_prefix == o.strip_prefix && + created_at == o.created_at && + updated_at == o.updated_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, project_id, frontend_id, function_id, path_prefix, strip_prefix, created_at, updated_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/frontend_function_route_list.rb b/lib/volcano/generated/lib/volcano-generated/models/frontend_function_route_list.rb new file mode 100644 index 00000000..626c6b11 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/frontend_function_route_list.rb @@ -0,0 +1,166 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class FrontendFunctionRouteList < ApiModelBase + attr_accessor :data + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::FrontendFunctionRouteList` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::FrontendFunctionRouteList`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/function.rb b/lib/volcano/generated/lib/volcano-generated/models/function.rb index cec760c9..5a8f1a4e 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/function.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/function.rb @@ -39,9 +39,7 @@ class Function < ApiModelBase # Whether OpenAPI metadata is configured; list responses omit the document itself. attr_accessor :has_openapi_spec - attr_accessor :aws_function_arn - - # Canonical GeoDNS endpoint URL for invoking this function (always HTTPS) + # Canonical geo-routed HTTPS endpoint for invoking this function. Use it as-is: it does not share a domain with the API, so a host derived from the API URL will not reach the function. Omitted when the deployment serves no public invocation domain, as in local development, so a client testing for an empty string never matches. attr_accessor :invoke_url # Regions where this function is currently deployed @@ -99,7 +97,6 @@ def self.attribute_map :'http_auth_mode' => :'http_auth_mode', :'openapi_spec' => :'openapi_spec', :'has_openapi_spec' => :'has_openapi_spec', - :'aws_function_arn' => :'aws_function_arn', :'invoke_url' => :'invoke_url', :'deployed_regions' => :'deployed_regions', :'runtime' => :'runtime', @@ -135,7 +132,6 @@ def self.openapi_types :'http_auth_mode' => :'FunctionHTTPAuthMode', :'openapi_spec' => :'Hash', :'has_openapi_spec' => :'Boolean', - :'aws_function_arn' => :'String', :'invoke_url' => :'String', :'deployed_regions' => :'Array', :'runtime' => :'String', @@ -231,10 +227,6 @@ def initialize(attributes = {}) self.has_openapi_spec = nil end - if attributes.key?(:'aws_function_arn') - self.aws_function_arn = attributes[:'aws_function_arn'] - end - if attributes.key?(:'invoke_url') self.invoke_url = attributes[:'invoke_url'] end @@ -497,7 +489,6 @@ def ==(o) http_auth_mode == o.http_auth_mode && openapi_spec == o.openapi_spec && has_openapi_spec == o.has_openapi_spec && - aws_function_arn == o.aws_function_arn && invoke_url == o.invoke_url && deployed_regions == o.deployed_regions && runtime == o.runtime && @@ -518,7 +509,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [id, project_id, name, status, provisioning_started_at, is_public, invocation_mode, http_auth_mode, openapi_spec, has_openapi_spec, aws_function_arn, invoke_url, deployed_regions, runtime, handler, current_deployment_id, pending_deployment_id, last_invoked_at, created_at, updated_at].hash + [id, project_id, name, status, provisioning_started_at, is_public, invocation_mode, http_auth_mode, openapi_spec, has_openapi_spec, invoke_url, deployed_regions, runtime, handler, current_deployment_id, pending_deployment_id, last_invoked_at, created_at, updated_at].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/function_deployment.rb b/lib/volcano/generated/lib/volcano-generated/models/function_deployment.rb index 96286b70..6b7c3ef6 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/function_deployment.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/function_deployment.rb @@ -33,19 +33,14 @@ class FunctionDeployment < ApiModelBase # Platform user that triggered a request-initiated deployment; absent for git and system deployments. attr_accessor :initiated_by - attr_accessor :artifact_bucket + # Total build time recorded for this deployment, in seconds. + attr_accessor :build_duration_seconds - attr_accessor :artifact_key + # Number of completed builds included in build_duration_seconds. + attr_accessor :build_count - attr_accessor :artifact_version - - # Total CodeBuild build duration recorded for this deployment, in seconds. - attr_accessor :codebuild_duration_seconds - - # Number of completed CodeBuild builds included in codebuild_duration_seconds. - attr_accessor :codebuild_build_count - - attr_accessor :codebuild_duration_recorded_at + # When the build time was last recorded. + attr_accessor :build_duration_recorded_at attr_accessor :progress @@ -90,12 +85,9 @@ def self.attribute_map :'status' => :'status', :'deploy_source' => :'deploy_source', :'initiated_by' => :'initiated_by', - :'artifact_bucket' => :'artifact_bucket', - :'artifact_key' => :'artifact_key', - :'artifact_version' => :'artifact_version', - :'codebuild_duration_seconds' => :'codebuild_duration_seconds', - :'codebuild_build_count' => :'codebuild_build_count', - :'codebuild_duration_recorded_at' => :'codebuild_duration_recorded_at', + :'build_duration_seconds' => :'build_duration_seconds', + :'build_count' => :'build_count', + :'build_duration_recorded_at' => :'build_duration_recorded_at', :'progress' => :'progress', :'error_message' => :'error_message', :'completed_at' => :'completed_at', @@ -125,12 +117,9 @@ def self.openapi_types :'status' => :'String', :'deploy_source' => :'String', :'initiated_by' => :'String', - :'artifact_bucket' => :'String', - :'artifact_key' => :'String', - :'artifact_version' => :'String', - :'codebuild_duration_seconds' => :'Integer', - :'codebuild_build_count' => :'Integer', - :'codebuild_duration_recorded_at' => :'Time', + :'build_duration_seconds' => :'Integer', + :'build_count' => :'Integer', + :'build_duration_recorded_at' => :'Time', :'progress' => :'DeploymentProgress', :'error_message' => :'String', :'completed_at' => :'Time', @@ -205,28 +194,16 @@ def initialize(attributes = {}) self.initiated_by = attributes[:'initiated_by'] end - if attributes.key?(:'artifact_bucket') - self.artifact_bucket = attributes[:'artifact_bucket'] - end - - if attributes.key?(:'artifact_key') - self.artifact_key = attributes[:'artifact_key'] - end - - if attributes.key?(:'artifact_version') - self.artifact_version = attributes[:'artifact_version'] - end - - if attributes.key?(:'codebuild_duration_seconds') - self.codebuild_duration_seconds = attributes[:'codebuild_duration_seconds'] + if attributes.key?(:'build_duration_seconds') + self.build_duration_seconds = attributes[:'build_duration_seconds'] end - if attributes.key?(:'codebuild_build_count') - self.codebuild_build_count = attributes[:'codebuild_build_count'] + if attributes.key?(:'build_count') + self.build_count = attributes[:'build_count'] end - if attributes.key?(:'codebuild_duration_recorded_at') - self.codebuild_duration_recorded_at = attributes[:'codebuild_duration_recorded_at'] + if attributes.key?(:'build_duration_recorded_at') + self.build_duration_recorded_at = attributes[:'build_duration_recorded_at'] end if attributes.key?(:'progress') @@ -408,12 +385,9 @@ def ==(o) status == o.status && deploy_source == o.deploy_source && initiated_by == o.initiated_by && - artifact_bucket == o.artifact_bucket && - artifact_key == o.artifact_key && - artifact_version == o.artifact_version && - codebuild_duration_seconds == o.codebuild_duration_seconds && - codebuild_build_count == o.codebuild_build_count && - codebuild_duration_recorded_at == o.codebuild_duration_recorded_at && + build_duration_seconds == o.build_duration_seconds && + build_count == o.build_count && + build_duration_recorded_at == o.build_duration_recorded_at && progress == o.progress && error_message == o.error_message && completed_at == o.completed_at && @@ -430,7 +404,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [id, function_id, project_id, batch_id, operation, status, deploy_source, initiated_by, artifact_bucket, artifact_key, artifact_version, codebuild_duration_seconds, codebuild_build_count, codebuild_duration_recorded_at, progress, error_message, completed_at, created_at, updated_at].hash + [id, function_id, project_id, batch_id, operation, status, deploy_source, initiated_by, build_duration_seconds, build_count, build_duration_recorded_at, progress, error_message, completed_at, created_at, updated_at].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/function_runtime_option.rb b/lib/volcano/generated/lib/volcano-generated/models/function_runtime_option.rb index 74fb5d78..e8c43082 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/function_runtime_option.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/function_runtime_option.rb @@ -18,6 +18,9 @@ class FunctionRuntimeOption < ApiModelBase # Runtime identifier accepted by function APIs. attr_accessor :name + # Human-readable runtime label suitable for display in pickers. + attr_accessor :label + # Runtime language family used by the CLI to choose defaults from source files. attr_accessor :language @@ -33,6 +36,7 @@ class FunctionRuntimeOption < ApiModelBase def self.attribute_map { :'name' => :'name', + :'label' => :'label', :'language' => :'language', :'default' => :'default', :'durable_capable' => :'durable_capable', @@ -54,6 +58,7 @@ def self.acceptable_attributes def self.openapi_types { :'name' => :'String', + :'label' => :'String', :'language' => :'String', :'default' => :'Boolean', :'durable_capable' => :'Boolean', @@ -89,6 +94,12 @@ def initialize(attributes = {}) self.name = nil end + if attributes.key?(:'label') + self.label = attributes[:'label'] + else + self.label = nil + end + if attributes.key?(:'language') self.language = attributes[:'language'] else @@ -123,6 +134,10 @@ def list_invalid_properties invalid_properties.push('invalid value for "name", name cannot be nil.') end + if @label.nil? + invalid_properties.push('invalid value for "label", label cannot be nil.') + end + if @language.nil? invalid_properties.push('invalid value for "language", language cannot be nil.') end @@ -147,6 +162,7 @@ def list_invalid_properties def valid? warn '[DEPRECATED] the `valid?` method is obsolete' return false if @name.nil? + return false if @label.nil? return false if @language.nil? return false if @default.nil? return false if @durable_capable.nil? @@ -164,6 +180,16 @@ def name=(name) @name = name end + # Custom attribute writer method with validation + # @param [Object] label Value to be assigned + def label=(label) + if label.nil? + fail ArgumentError, 'label cannot be nil' + end + + @label = label + end + # Custom attribute writer method with validation # @param [Object] language Value to be assigned def language=(language) @@ -210,6 +236,7 @@ def ==(o) return true if self.equal?(o) self.class == o.class && name == o.name && + label == o.label && language == o.language && default == o.default && durable_capable == o.durable_capable && @@ -225,7 +252,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [name, language, default, durable_capable, deployment].hash + [name, label, language, default, durable_capable, deployment].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/log_activity_bucket.rb b/lib/volcano/generated/lib/volcano-generated/models/log_activity_bucket.rb index 000c4deb..48b473b1 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/log_activity_bucket.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/log_activity_bucket.rb @@ -14,12 +14,12 @@ require 'time' module Volcano::Generated - # Log-event counts for one activity time bucket. + # Log-event counts for one activity time bucket. The first and last buckets can extend past the requested window; they count only events inside it. class LogActivityBucket < ApiModelBase - # Bucket start time. + # Bucket start time, inclusive. attr_accessor :start_time - # Bucket end time. + # Bucket end time, exclusive. attr_accessor :end_time attr_accessor :counts diff --git a/lib/volcano/generated/lib/volcano-generated/models/log_activity_request.rb b/lib/volcano/generated/lib/volcano-generated/models/log_activity_request.rb index 00f914e4..705cd981 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/log_activity_request.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/log_activity_request.rb @@ -21,13 +21,13 @@ class LogActivityRequest < ApiModelBase # Optional activity query. Supports quoted text, implicit AND, AND/OR/NOT, parentheses, and fields such as `level`, `region`, `invocation.id`, `resource.id`, `resource.name`, `function`, `frontend`, `database`, and `body`. attr_accessor :q - # Start time. + # Start of the window, inclusive. Defaults to 24 hours before `end_time`. attr_accessor :start_time - # End time. + # End of the window, exclusive. Defaults to now. attr_accessor :end_time - # Number of activity buckets to return. + # Maximum number of buckets. Defaults to 24. Volcano picks the smallest bucket width from 1s, 2s, 5s, 10s, 15s, 30s, 1m, 2m, 5m, 10m, 15m, 30m, 1h, 2h, 3h, 6h, 12h, 1d, or a whole number of days that covers the window in at most this many buckets. Bucket edges fall on UTC multiples of the width, so they stay fixed as the window moves, and the response can contain fewer buckets. `1` returns one bucket that spans exactly the window. attr_accessor :bucket_count # Attribute mapping from ruby-style variable name to JSON key. diff --git a/lib/volcano/generated/lib/volcano-generated/models/log_search_response.rb b/lib/volcano/generated/lib/volcano-generated/models/log_search_response.rb index 0203f9db..66f169c8 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/log_search_response.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/log_search_response.rb @@ -22,10 +22,10 @@ class LogSearchResponse < ApiModelBase # Number of items requested per page. attr_accessor :limit - # Whether there are more log events available. + # Whether the search may have more matching log events. A page can hold fewer than `limit` events, or none, while this is true; keep paging until it is false. attr_accessor :has_more - # Opaque cursor for the next page. Send this value as `cursor` on the next request. + # Opaque cursor for the next page, present while `has_more` is true. Send this value as `cursor` on the next request, even when `data` is empty. attr_accessor :next_cursor # Attribute mapping from ruby-style variable name to JSON key. diff --git a/lib/volcano/generated/lib/volcano-generated/models/metric_usage_data.rb b/lib/volcano/generated/lib/volcano-generated/models/metric_usage_data.rb index bef00e5e..b9c05f05 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/metric_usage_data.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/metric_usage_data.rb @@ -16,7 +16,7 @@ module Volcano::Generated # Usage data for one metric across totals, daily, and hourly windows. class MetricUsageData < ApiModelBase - # Metric name (for example, \"Function & Frontend Invocations\", \"Frontend Requests\", \"Durable Executions\", \"Durable Operations\", \"Durable Compute (MB-Seconds)\", \"CodeBuild Build Seconds\", \"Bandwidth Ingress (Bytes)\", \"Bandwidth Egress (Bytes)\", \"Bandwidth Total (Bytes)\", or \"Database Storage (Bytes)\"). Byte-based metrics are reported in bytes. \"Bandwidth Total (Bytes)\" is derived (ingress + egress) and is not billed separately. The three durable metrics are counted separately from \"Function & Frontend Invocations\", which covers standard invocations only. Operations and compute are counted when an execution finishes, so they appear in the window the execution completed in rather than the one it started in. \"Durable Compute (MB-Seconds)\" reports the memory the execution ran at times the time it spent running, in megabyte-seconds; the allowance for it is published in gigabyte-seconds, which is 1024 of these. \"Database Storage (Bytes)\" is a current observed gauge, not a cumulative counter. It is the sum of the latest samples exposed as `storage_bytes` by the project's database list, so it includes what each database's branches and backups hold, and it inherits that field's lag behind a live measurement. + # Metric name (for example, \"Function & Frontend Invocations\", \"Frontend Requests\", \"Durable Executions\", \"Durable Operations\", \"Durable Compute (MB-Seconds)\", \"Build Seconds\", \"Bandwidth Ingress (Bytes)\", \"Bandwidth Egress (Bytes)\", \"Bandwidth Total (Bytes)\", or \"Database Storage (Bytes)\"). Byte-based metrics are reported in bytes. \"Bandwidth Total (Bytes)\" is derived (ingress + egress) and is not billed separately. The three durable metrics are counted separately from \"Function & Frontend Invocations\", which covers standard invocations only. Operations and compute are counted when an execution finishes, so they appear in the window the execution completed in rather than the one it started in. \"Durable Compute (MB-Seconds)\" reports the memory the execution ran at times the time it spent running, in megabyte-seconds; the allowance for it is published in gigabyte-seconds, which is 1024 of these. \"Database Storage (Bytes)\" is a current observed gauge, not a cumulative counter. It is the sum of the latest samples exposed as `storage_bytes` by the project's database list, so it includes what each database's branches and backups hold, and it inherits that field's lag behind a live measurement. attr_accessor :metric # Total usage for the current usage month diff --git a/lib/volcano/generated/lib/volcano-generated/models/paginated_project_access_tokens.rb b/lib/volcano/generated/lib/volcano-generated/models/paginated_project_access_tokens.rb new file mode 100644 index 00000000..47ded4e8 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/paginated_project_access_tokens.rb @@ -0,0 +1,279 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class PaginatedProjectAccessTokens < ApiModelBase + attr_accessor :data + + attr_accessor :page + + attr_accessor :limit + + attr_accessor :total + + attr_accessor :has_more + + attr_accessor :_next + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data', + :'page' => :'page', + :'limit' => :'limit', + :'total' => :'total', + :'has_more' => :'has_more', + :'_next' => :'next' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array', + :'page' => :'Integer', + :'limit' => :'Integer', + :'total' => :'Integer', + :'has_more' => :'Boolean', + :'_next' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::PaginatedProjectAccessTokens` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::PaginatedProjectAccessTokens`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + + if attributes.key?(:'page') + self.page = attributes[:'page'] + else + self.page = nil + end + + if attributes.key?(:'limit') + self.limit = attributes[:'limit'] + else + self.limit = nil + end + + if attributes.key?(:'total') + self.total = attributes[:'total'] + else + self.total = nil + end + + if attributes.key?(:'has_more') + self.has_more = attributes[:'has_more'] + else + self.has_more = nil + end + + if attributes.key?(:'_next') + self._next = attributes[:'_next'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + if @page.nil? + invalid_properties.push('invalid value for "page", page cannot be nil.') + end + + if @limit.nil? + invalid_properties.push('invalid value for "limit", limit cannot be nil.') + end + + if @total.nil? + invalid_properties.push('invalid value for "total", total cannot be nil.') + end + + if @has_more.nil? + invalid_properties.push('invalid value for "has_more", has_more cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + return false if @page.nil? + return false if @limit.nil? + return false if @total.nil? + return false if @has_more.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Custom attribute writer method with validation + # @param [Object] page Value to be assigned + def page=(page) + if page.nil? + fail ArgumentError, 'page cannot be nil' + end + + @page = page + end + + # Custom attribute writer method with validation + # @param [Object] limit Value to be assigned + def limit=(limit) + if limit.nil? + fail ArgumentError, 'limit cannot be nil' + end + + @limit = limit + end + + # Custom attribute writer method with validation + # @param [Object] total Value to be assigned + def total=(total) + if total.nil? + fail ArgumentError, 'total cannot be nil' + end + + @total = total + end + + # Custom attribute writer method with validation + # @param [Object] has_more Value to be assigned + def has_more=(has_more) + if has_more.nil? + fail ArgumentError, 'has_more cannot be nil' + end + + @has_more = has_more + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data && + page == o.page && + limit == o.limit && + total == o.total && + has_more == o.has_more && + _next == o._next + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data, page, limit, total, has_more, _next].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/project.rb b/lib/volcano/generated/lib/volcano-generated/models/project.rb index 1ea28f5f..7c85ab71 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project.rb @@ -21,7 +21,7 @@ class Project < ApiModelBase attr_accessor :status - # Public plan name; FREE and PRO are accepted from older Hosting responses. + # Plan name applied to the project when available. attr_accessor :plan # Region policy for function deployment. - `true`: deploy functions to all configured platform regions - `false`: deploy only to `selected_regions` @@ -30,8 +30,6 @@ class Project < ApiModelBase # Effective region set for this project (normalized and deduplicated) attr_accessor :selected_regions - attr_accessor :aws_application_name - # Most recent activity timestamp across project resources attr_accessor :last_invoked_at @@ -79,7 +77,6 @@ def self.attribute_map :'plan' => :'plan', :'all_regions' => :'all_regions', :'selected_regions' => :'selected_regions', - :'aws_application_name' => :'aws_application_name', :'last_invoked_at' => :'last_invoked_at', :'logo_url' => :'logo_url', :'git_connection' => :'git_connection', @@ -108,7 +105,6 @@ def self.openapi_types :'plan' => :'String', :'all_regions' => :'Boolean', :'selected_regions' => :'Array', - :'aws_application_name' => :'String', :'last_invoked_at' => :'Time', :'logo_url' => :'String', :'git_connection' => :'ProjectGitConnectionSummary', @@ -176,10 +172,6 @@ def initialize(attributes = {}) self.selected_regions = nil end - if attributes.key?(:'aws_application_name') - self.aws_application_name = attributes[:'aws_application_name'] - end - if attributes.key?(:'last_invoked_at') self.last_invoked_at = attributes[:'last_invoked_at'] end @@ -254,7 +246,7 @@ def valid? return false if @status.nil? status_validator = EnumAttributeValidator.new('String', ["active", "deleting", "failed"]) return false unless status_validator.valid?(@status) - plan_validator = EnumAttributeValidator.new('String', ["HOBBY", "SUPERAGENT", "FREE", "PRO"]) + plan_validator = EnumAttributeValidator.new('String', ["HOBBY", "SUPERAGENT"]) return false unless plan_validator.valid?(@plan) return false if @all_regions.nil? return false if @selected_regions.nil? @@ -296,7 +288,7 @@ def status=(status) # Custom attribute writer method checking allowed values (enum). # @param [Object] plan Object to be assigned def plan=(plan) - validator = EnumAttributeValidator.new('String', ["HOBBY", "SUPERAGENT", "FREE", "PRO"]) + validator = EnumAttributeValidator.new('String', ["HOBBY", "SUPERAGENT"]) unless validator.valid?(plan) fail ArgumentError, "invalid value for \"plan\", must be one of #{validator.allowable_values}." end @@ -354,7 +346,6 @@ def ==(o) plan == o.plan && all_regions == o.all_regions && selected_regions == o.selected_regions && - aws_application_name == o.aws_application_name && last_invoked_at == o.last_invoked_at && logo_url == o.logo_url && git_connection == o.git_connection && @@ -372,7 +363,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [id, name, status, plan, all_regions, selected_regions, aws_application_name, last_invoked_at, logo_url, git_connection, health, created_at, updated_at].hash + [id, name, status, plan, all_regions, selected_regions, last_invoked_at, logo_url, git_connection, health, created_at, updated_at].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_access_token.rb b/lib/volcano/generated/lib/volcano-generated/models/project_access_token.rb new file mode 100644 index 00000000..b665fe93 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/project_access_token.rb @@ -0,0 +1,426 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # A project access token: a control-plane credential bound to a single project. Unlike a platform token, which acts on every project its owner has, this one is limited to the project it was created in. The secret itself is never returned here. Only its hash is stored, so the plaintext exists solely in the response to the create call. + class ProjectAccessToken < ApiModelBase + attr_accessor :id + + attr_accessor :project_id + + # Unique per project. + attr_accessor :name + + # First 12 characters of the secret, for recognising a token in a list. + attr_accessor :token_prefix + + attr_accessor :scope + + # `revoked` means the token was deliberately revoked, by you or by the deletion of its project. `expired` means it simply reached `expires_at`; nothing was taken away. Both are refused, and both keep their record so a token's name, prefix, last use, and request history remain available after a leak. A token revoked before its expiry passed stays `revoked`, because that is the fact worth keeping. + attr_accessor :status + + # What created the token. + attr_accessor :token_source + + # Absent for a token that does not expire. + attr_accessor :expires_at + + # Updated at most once every few minutes, so it may lag slightly. + attr_accessor :last_used_at + + attr_accessor :created_at + + # Requests authenticated with this token since it was created. + attr_accessor :all_time_requests + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'project_id' => :'project_id', + :'name' => :'name', + :'token_prefix' => :'token_prefix', + :'scope' => :'scope', + :'status' => :'status', + :'token_source' => :'token_source', + :'expires_at' => :'expires_at', + :'last_used_at' => :'last_used_at', + :'created_at' => :'created_at', + :'all_time_requests' => :'all_time_requests' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'project_id' => :'String', + :'name' => :'String', + :'token_prefix' => :'String', + :'scope' => :'ProjectAccessTokenScope', + :'status' => :'String', + :'token_source' => :'String', + :'expires_at' => :'Time', + :'last_used_at' => :'Time', + :'created_at' => :'Time', + :'all_time_requests' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + :'expires_at', + :'last_used_at', + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::ProjectAccessToken` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::ProjectAccessToken`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'project_id') + self.project_id = attributes[:'project_id'] + else + self.project_id = nil + end + + if attributes.key?(:'name') + self.name = attributes[:'name'] + else + self.name = nil + end + + if attributes.key?(:'token_prefix') + self.token_prefix = attributes[:'token_prefix'] + else + self.token_prefix = nil + end + + if attributes.key?(:'scope') + self.scope = attributes[:'scope'] + else + self.scope = nil + end + + if attributes.key?(:'status') + self.status = attributes[:'status'] + else + self.status = nil + end + + if attributes.key?(:'token_source') + self.token_source = attributes[:'token_source'] + else + self.token_source = nil + end + + if attributes.key?(:'expires_at') + self.expires_at = attributes[:'expires_at'] + end + + if attributes.key?(:'last_used_at') + self.last_used_at = attributes[:'last_used_at'] + end + + if attributes.key?(:'created_at') + self.created_at = attributes[:'created_at'] + else + self.created_at = nil + end + + if attributes.key?(:'all_time_requests') + self.all_time_requests = attributes[:'all_time_requests'] + else + self.all_time_requests = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @project_id.nil? + invalid_properties.push('invalid value for "project_id", project_id cannot be nil.') + end + + if @name.nil? + invalid_properties.push('invalid value for "name", name cannot be nil.') + end + + if @token_prefix.nil? + invalid_properties.push('invalid value for "token_prefix", token_prefix cannot be nil.') + end + + if @scope.nil? + invalid_properties.push('invalid value for "scope", scope cannot be nil.') + end + + if @status.nil? + invalid_properties.push('invalid value for "status", status cannot be nil.') + end + + if @token_source.nil? + invalid_properties.push('invalid value for "token_source", token_source cannot be nil.') + end + + if @created_at.nil? + invalid_properties.push('invalid value for "created_at", created_at cannot be nil.') + end + + if @all_time_requests.nil? + invalid_properties.push('invalid value for "all_time_requests", all_time_requests cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @project_id.nil? + return false if @name.nil? + return false if @token_prefix.nil? + return false if @scope.nil? + return false if @status.nil? + status_validator = EnumAttributeValidator.new('String', ["active", "revoked", "expired"]) + return false unless status_validator.valid?(@status) + return false if @token_source.nil? + token_source_validator = EnumAttributeValidator.new('String', ["api", "cli", "dashboard"]) + return false unless token_source_validator.valid?(@token_source) + return false if @created_at.nil? + return false if @all_time_requests.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method with validation + # @param [Object] project_id Value to be assigned + def project_id=(project_id) + if project_id.nil? + fail ArgumentError, 'project_id cannot be nil' + end + + @project_id = project_id + end + + # Custom attribute writer method with validation + # @param [Object] name Value to be assigned + def name=(name) + if name.nil? + fail ArgumentError, 'name cannot be nil' + end + + @name = name + end + + # Custom attribute writer method with validation + # @param [Object] token_prefix Value to be assigned + def token_prefix=(token_prefix) + if token_prefix.nil? + fail ArgumentError, 'token_prefix cannot be nil' + end + + @token_prefix = token_prefix + end + + # Custom attribute writer method with validation + # @param [Object] scope Value to be assigned + def scope=(scope) + if scope.nil? + fail ArgumentError, 'scope cannot be nil' + end + + @scope = scope + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] status Object to be assigned + def status=(status) + validator = EnumAttributeValidator.new('String', ["active", "revoked", "expired"]) + unless validator.valid?(status) + fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}." + end + @status = status + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] token_source Object to be assigned + def token_source=(token_source) + validator = EnumAttributeValidator.new('String', ["api", "cli", "dashboard"]) + unless validator.valid?(token_source) + fail ArgumentError, "invalid value for \"token_source\", must be one of #{validator.allowable_values}." + end + @token_source = token_source + end + + # Custom attribute writer method with validation + # @param [Object] created_at Value to be assigned + def created_at=(created_at) + if created_at.nil? + fail ArgumentError, 'created_at cannot be nil' + end + + @created_at = created_at + end + + # Custom attribute writer method with validation + # @param [Object] all_time_requests Value to be assigned + def all_time_requests=(all_time_requests) + if all_time_requests.nil? + fail ArgumentError, 'all_time_requests cannot be nil' + end + + @all_time_requests = all_time_requests + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + project_id == o.project_id && + name == o.name && + token_prefix == o.token_prefix && + scope == o.scope && + status == o.status && + token_source == o.token_source && + expires_at == o.expires_at && + last_used_at == o.last_used_at && + created_at == o.created_at && + all_time_requests == o.all_time_requests + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, project_id, name, token_prefix, scope, status, token_source, expires_at, last_used_at, created_at, all_time_requests].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_access_token_scope.rb b/lib/volcano/generated/lib/volcano-generated/models/project_access_token_scope.rb new file mode 100644 index 00000000..e0fb177f --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/project_access_token_scope.rb @@ -0,0 +1,40 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class ProjectAccessTokenScope + ProjectAccessTokenScopeFull = "full".freeze + ProjectAccessTokenScopeReadOnly = "read_only".freeze + + def self.all_vars + @all_vars ||= [ProjectAccessTokenScopeFull, ProjectAccessTokenScopeReadOnly].freeze + end + + # Builds the enum from string + # @param [String] The enum value in the form of the string + # @return [String] The enum value + def self.build_from_hash(value) + new.build_from_hash(value) + end + + # Builds the enum from string + # @param [String] The enum value in the form of the string + # @return [String] The enum value + def build_from_hash(value) + return value if ProjectAccessTokenScope.all_vars.include?(value) + raise "Invalid ENUM value #{value} for class #ProjectAccessTokenScope" + end + end +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage.rb b/lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage.rb new file mode 100644 index 00000000..4e06e73b --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage.rb @@ -0,0 +1,299 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + # Zero-filled daily request counts for a single token, oldest first. Every day in the window is present, so a gap reads as zero rather than missing. Counts every request the token authenticated, including ones then refused — a read-only token attempting a write, or a token presented on another project's route. That is deliberate: after a leak, the probing is the part you want to see, and a counter that hid it would make a token look idle while it was being tried. + class ProjectAccessTokenUsage < ApiModelBase + attr_accessor :token_id + + attr_accessor :name + + # The token's display prefix, which identifies the credential when its name does not. Revoking frees a name, so a project that rotated `ci-deploy` has two entries here both called `ci-deploy`. Not usable as a credential. + attr_accessor :token_prefix + + # Number of daily entries returned, always equal to the requested window. + attr_accessor :days + + attr_accessor :daily + + attr_accessor :total_requests + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'token_id' => :'token_id', + :'name' => :'name', + :'token_prefix' => :'token_prefix', + :'days' => :'days', + :'daily' => :'daily', + :'total_requests' => :'total_requests' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'token_id' => :'String', + :'name' => :'String', + :'token_prefix' => :'String', + :'days' => :'Integer', + :'daily' => :'Array', + :'total_requests' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::ProjectAccessTokenUsage` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::ProjectAccessTokenUsage`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'token_id') + self.token_id = attributes[:'token_id'] + else + self.token_id = nil + end + + if attributes.key?(:'name') + self.name = attributes[:'name'] + else + self.name = nil + end + + if attributes.key?(:'token_prefix') + self.token_prefix = attributes[:'token_prefix'] + else + self.token_prefix = nil + end + + if attributes.key?(:'days') + self.days = attributes[:'days'] + else + self.days = nil + end + + if attributes.key?(:'daily') + if (value = attributes[:'daily']).is_a?(Array) + self.daily = value + end + else + self.daily = nil + end + + if attributes.key?(:'total_requests') + self.total_requests = attributes[:'total_requests'] + else + self.total_requests = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @token_id.nil? + invalid_properties.push('invalid value for "token_id", token_id cannot be nil.') + end + + if @name.nil? + invalid_properties.push('invalid value for "name", name cannot be nil.') + end + + if @token_prefix.nil? + invalid_properties.push('invalid value for "token_prefix", token_prefix cannot be nil.') + end + + if @days.nil? + invalid_properties.push('invalid value for "days", days cannot be nil.') + end + + if @daily.nil? + invalid_properties.push('invalid value for "daily", daily cannot be nil.') + end + + if @total_requests.nil? + invalid_properties.push('invalid value for "total_requests", total_requests cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @token_id.nil? + return false if @name.nil? + return false if @token_prefix.nil? + return false if @days.nil? + return false if @daily.nil? + return false if @total_requests.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] token_id Value to be assigned + def token_id=(token_id) + if token_id.nil? + fail ArgumentError, 'token_id cannot be nil' + end + + @token_id = token_id + end + + # Custom attribute writer method with validation + # @param [Object] name Value to be assigned + def name=(name) + if name.nil? + fail ArgumentError, 'name cannot be nil' + end + + @name = name + end + + # Custom attribute writer method with validation + # @param [Object] token_prefix Value to be assigned + def token_prefix=(token_prefix) + if token_prefix.nil? + fail ArgumentError, 'token_prefix cannot be nil' + end + + @token_prefix = token_prefix + end + + # Custom attribute writer method with validation + # @param [Object] days Value to be assigned + def days=(days) + if days.nil? + fail ArgumentError, 'days cannot be nil' + end + + @days = days + end + + # Custom attribute writer method with validation + # @param [Object] daily Value to be assigned + def daily=(daily) + if daily.nil? + fail ArgumentError, 'daily cannot be nil' + end + + @daily = daily + end + + # Custom attribute writer method with validation + # @param [Object] total_requests Value to be assigned + def total_requests=(total_requests) + if total_requests.nil? + fail ArgumentError, 'total_requests cannot be nil' + end + + @total_requests = total_requests + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + token_id == o.token_id && + name == o.name && + token_prefix == o.token_prefix && + days == o.days && + daily == o.daily && + total_requests == o.total_requests + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [token_id, name, token_prefix, days, daily, total_requests].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage_daily_entry.rb b/lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage_daily_entry.rb new file mode 100644 index 00000000..a5b9d82c --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/project_access_token_usage_daily_entry.rb @@ -0,0 +1,191 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class ProjectAccessTokenUsageDailyEntry < ApiModelBase + # UTC day. + attr_accessor :day + + attr_accessor :requests + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'day' => :'day', + :'requests' => :'requests' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'day' => :'Date', + :'requests' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::ProjectAccessTokenUsageDailyEntry` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::ProjectAccessTokenUsageDailyEntry`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'day') + self.day = attributes[:'day'] + else + self.day = nil + end + + if attributes.key?(:'requests') + self.requests = attributes[:'requests'] + else + self.requests = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @day.nil? + invalid_properties.push('invalid value for "day", day cannot be nil.') + end + + if @requests.nil? + invalid_properties.push('invalid value for "requests", requests cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @day.nil? + return false if @requests.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] day Value to be assigned + def day=(day) + if day.nil? + fail ArgumentError, 'day cannot be nil' + end + + @day = day + end + + # Custom attribute writer method with validation + # @param [Object] requests Value to be assigned + def requests=(requests) + if requests.nil? + fail ArgumentError, 'requests cannot be nil' + end + + @requests = requests + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + day == o.day && + requests == o.requests + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [day, requests].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_config.rb b/lib/volcano/generated/lib/volcano-generated/models/project_config.rb index c95bfced..cc9f2e1e 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project_config.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project_config.rb @@ -26,6 +26,9 @@ class ProjectConfig < ApiModelBase # Replace the complete shared function-variable list with existing names, without changing variable values. Omission keeps membership unchanged; an empty list clears it. attr_accessor :shared_variables + # Replace the complete shared frontend-variable list with existing names. Frontends with variable_scope shared receive this list. Omission keeps membership unchanged; an empty list clears it. + attr_accessor :frontend_shared_variables + # Fully synced when declared - variables absent from this list are deleted. attr_accessor :variables @@ -68,6 +71,7 @@ def self.attribute_map :'project' => :'project', :'databases' => :'databases', :'shared_variables' => :'shared_variables', + :'frontend_shared_variables' => :'frontend_shared_variables', :'variables' => :'variables', :'buckets' => :'buckets', :'realtime' => :'realtime', @@ -94,6 +98,7 @@ def self.openapi_types :'project' => :'ProjectConfigProject', :'databases' => :'Array', :'shared_variables' => :'Array', + :'frontend_shared_variables' => :'Array', :'variables' => :'Array', :'buckets' => :'Array', :'realtime' => :'ProjectConfigRealtime', @@ -147,6 +152,12 @@ def initialize(attributes = {}) end end + if attributes.key?(:'frontend_shared_variables') + if (value = attributes[:'frontend_shared_variables']).is_a?(Array) + self.frontend_shared_variables = value + end + end + if attributes.key?(:'variables') if (value = attributes[:'variables']).is_a?(Array) self.variables = value @@ -222,6 +233,16 @@ def shared_variables=(shared_variables) @shared_variables = shared_variables end + # Custom attribute writer method with validation + # @param [Object] frontend_shared_variables Value to be assigned + def frontend_shared_variables=(frontend_shared_variables) + if frontend_shared_variables.nil? + fail ArgumentError, 'frontend_shared_variables cannot be nil' + end + + @frontend_shared_variables = frontend_shared_variables + end + # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) @@ -231,6 +252,7 @@ def ==(o) project == o.project && databases == o.databases && shared_variables == o.shared_variables && + frontend_shared_variables == o.frontend_shared_variables && variables == o.variables && buckets == o.buckets && realtime == o.realtime && @@ -248,7 +270,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [version, project, databases, shared_variables, variables, buckets, realtime, auth, functions, frontends].hash + [version, project, databases, shared_variables, frontend_shared_variables, variables, buckets, realtime, auth, functions, frontends].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_config_database.rb b/lib/volcano/generated/lib/volcano-generated/models/project_config_database.rb index e265a7ca..fe150a1e 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project_config_database.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project_config_database.rb @@ -18,7 +18,7 @@ module Volcano::Generated class ProjectConfigDatabase < ApiModelBase attr_accessor :name - # Deployed region ID (e.g. aws-us-east-1). Asserted, never written. + # Deployed region ID (e.g. us-east-1). Asserted, never written; region IDs issued by earlier versions of the API match too. attr_accessor :region # PostgreSQL major version. Asserted, never written. diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_config_frontend.rb b/lib/volcano/generated/lib/volcano-generated/models/project_config_frontend.rb index 740c301f..072ed4b6 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project_config_frontend.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project_config_frontend.rb @@ -16,15 +16,49 @@ module Volcano::Generated # Configuration for an existing (deployed) frontend. Frontends are never created or deleted through the manifest. A declared frontend entry without `custom_domain` deletes an existing custom domain. class ProjectConfigFrontend < ApiModelBase + # All preserves access to all project variables. Shared includes the project frontend_shared_variables list. Scoped includes only explicitly declared variables in builds and runtime. Omission preserves the stored selection. + attr_accessor :variable_scope + + # Names selected when variable_scope is scoped. Missing declared values reject deployment. Omission preserves the stored list; an empty list clears it. + attr_accessor :variables + attr_accessor :name attr_accessor :custom_domain + # Complete set of same-origin Function path mappings when declared. Omission preserves existing mappings; an empty list deletes all mappings. + attr_accessor :function_routes + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + # Attribute mapping from ruby-style variable name to JSON key. def self.attribute_map { + :'variable_scope' => :'variable_scope', + :'variables' => :'variables', :'name' => :'name', - :'custom_domain' => :'custom_domain' + :'custom_domain' => :'custom_domain', + :'function_routes' => :'function_routes' } end @@ -41,8 +75,11 @@ def self.acceptable_attributes # Attribute type mapping. def self.openapi_types { + :'variable_scope' => :'String', + :'variables' => :'Array', :'name' => :'String', - :'custom_domain' => :'ProjectConfigCustomDomain' + :'custom_domain' => :'ProjectConfigCustomDomain', + :'function_routes' => :'Array' } end @@ -68,6 +105,16 @@ def initialize(attributes = {}) h[k.to_sym] = v } + if attributes.key?(:'variable_scope') + self.variable_scope = attributes[:'variable_scope'] + end + + if attributes.key?(:'variables') + if (value = attributes[:'variables']).is_a?(Array) + self.variables = value + end + end + if attributes.key?(:'name') self.name = attributes[:'name'] else @@ -77,6 +124,12 @@ def initialize(attributes = {}) if attributes.key?(:'custom_domain') self.custom_domain = attributes[:'custom_domain'] end + + if attributes.key?(:'function_routes') + if (value = attributes[:'function_routes']).is_a?(Array) + self.function_routes = value + end + end end # Show invalid properties with the reasons. Usually used together with valid? @@ -92,6 +145,10 @@ def list_invalid_properties invalid_properties.push('invalid value for "name", the character length must be greater than or equal to 1.') end + if !@function_routes.nil? && @function_routes.length > 64 + invalid_properties.push('invalid value for "function_routes", number of items must be less than or equal to 64.') + end + invalid_properties end @@ -99,11 +156,34 @@ def list_invalid_properties # @return true if the model is valid def valid? warn '[DEPRECATED] the `valid?` method is obsolete' + variable_scope_validator = EnumAttributeValidator.new('String', ["all", "shared", "scoped"]) + return false unless variable_scope_validator.valid?(@variable_scope) return false if @name.nil? return false if @name.to_s.length < 1 + return false if !@function_routes.nil? && @function_routes.length > 64 true end + # Custom attribute writer method checking allowed values (enum). + # @param [Object] variable_scope Object to be assigned + def variable_scope=(variable_scope) + validator = EnumAttributeValidator.new('String', ["all", "shared", "scoped"]) + unless validator.valid?(variable_scope) + fail ArgumentError, "invalid value for \"variable_scope\", must be one of #{validator.allowable_values}." + end + @variable_scope = variable_scope + end + + # Custom attribute writer method with validation + # @param [Object] variables Value to be assigned + def variables=(variables) + if variables.nil? + fail ArgumentError, 'variables cannot be nil' + end + + @variables = variables + end + # Custom attribute writer method with validation # @param [Object] name Value to be assigned def name=(name) @@ -118,13 +198,30 @@ def name=(name) @name = name end + # Custom attribute writer method with validation + # @param [Object] function_routes Value to be assigned + def function_routes=(function_routes) + if function_routes.nil? + fail ArgumentError, 'function_routes cannot be nil' + end + + if function_routes.length > 64 + fail ArgumentError, 'invalid value for "function_routes", number of items must be less than or equal to 64.' + end + + @function_routes = function_routes + end + # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) return true if self.equal?(o) self.class == o.class && + variable_scope == o.variable_scope && + variables == o.variables && name == o.name && - custom_domain == o.custom_domain + custom_domain == o.custom_domain && + function_routes == o.function_routes end # @see the `==` method @@ -136,7 +233,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [name, custom_domain].hash + [variable_scope, variables, name, custom_domain, function_routes].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_config_frontend_function_route.rb b/lib/volcano/generated/lib/volcano-generated/models/project_config_frontend_function_route.rb new file mode 100644 index 00000000..936c619e --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/project_config_frontend_function_route.rb @@ -0,0 +1,240 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class ProjectConfigFrontendFunctionRoute < ApiModelBase + # Name of an existing standard Function configured for HTTP invocation. + attr_accessor :function + + attr_accessor :path_prefix + + attr_accessor :strip_prefix + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'function' => :'function', + :'path_prefix' => :'path_prefix', + :'strip_prefix' => :'strip_prefix' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'function' => :'String', + :'path_prefix' => :'String', + :'strip_prefix' => :'Boolean' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::ProjectConfigFrontendFunctionRoute` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::ProjectConfigFrontendFunctionRoute`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'function') + self.function = attributes[:'function'] + else + self.function = nil + end + + if attributes.key?(:'path_prefix') + self.path_prefix = attributes[:'path_prefix'] + else + self.path_prefix = nil + end + + if attributes.key?(:'strip_prefix') + self.strip_prefix = attributes[:'strip_prefix'] + else + self.strip_prefix = false + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @function.nil? + invalid_properties.push('invalid value for "function", function cannot be nil.') + end + + if @function.to_s.length < 1 + invalid_properties.push('invalid value for "function", the character length must be greater than or equal to 1.') + end + + if @path_prefix.nil? + invalid_properties.push('invalid value for "path_prefix", path_prefix cannot be nil.') + end + + if @path_prefix.to_s.length > 512 + invalid_properties.push('invalid value for "path_prefix", the character length must be smaller than or equal to 512.') + end + + if @path_prefix.to_s.length < 2 + invalid_properties.push('invalid value for "path_prefix", the character length must be greater than or equal to 2.') + end + + pattern = Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + if @path_prefix !~ pattern + invalid_properties.push("invalid value for \"path_prefix\", must conform to the pattern #{pattern}.") + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @function.nil? + return false if @function.to_s.length < 1 + return false if @path_prefix.nil? + return false if @path_prefix.to_s.length > 512 + return false if @path_prefix.to_s.length < 2 + return false if @path_prefix !~ Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + true + end + + # Custom attribute writer method with validation + # @param [Object] function Value to be assigned + def function=(function) + if function.nil? + fail ArgumentError, 'function cannot be nil' + end + + if function.to_s.length < 1 + fail ArgumentError, 'invalid value for "function", the character length must be greater than or equal to 1.' + end + + @function = function + end + + # Custom attribute writer method with validation + # @param [Object] path_prefix Value to be assigned + def path_prefix=(path_prefix) + if path_prefix.nil? + fail ArgumentError, 'path_prefix cannot be nil' + end + + if path_prefix.to_s.length > 512 + fail ArgumentError, 'invalid value for "path_prefix", the character length must be smaller than or equal to 512.' + end + + if path_prefix.to_s.length < 2 + fail ArgumentError, 'invalid value for "path_prefix", the character length must be greater than or equal to 2.' + end + + pattern = Regexp.new(/^\/[^?#\\]*[^\/?#\\]$/) + if path_prefix !~ pattern + fail ArgumentError, "invalid value for \"path_prefix\", must conform to the pattern #{pattern}." + end + + @path_prefix = path_prefix + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + function == o.function && + path_prefix == o.path_prefix && + strip_prefix == o.strip_prefix + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [function, path_prefix, strip_prefix].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_config_variable.rb b/lib/volcano/generated/lib/volcano-generated/models/project_config_variable.rb index c2a7971e..0b4f1fad 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project_config_variable.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project_config_variable.rb @@ -18,6 +18,7 @@ class ProjectConfigVariable < ApiModelBase # Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable. attr_accessor :shared + # Project variable name. Function runtime names such as AWS_REGION are reserved and fail validation; see the environment variables guide for the full list. attr_accessor :name attr_accessor :value diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_deployment.rb b/lib/volcano/generated/lib/volcano-generated/models/project_deployment.rb index ea4e41d6..12442fec 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project_deployment.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project_deployment.rb @@ -29,8 +29,6 @@ class ProjectDeployment < ApiModelBase # What initiated this deployment. attr_accessor :deploy_source - attr_accessor :artifact_version - attr_accessor :error_message attr_accessor :completed_at @@ -72,7 +70,6 @@ def self.attribute_map :'operation' => :'operation', :'status' => :'status', :'deploy_source' => :'deploy_source', - :'artifact_version' => :'artifact_version', :'error_message' => :'error_message', :'completed_at' => :'completed_at', :'progress' => :'progress', @@ -100,7 +97,6 @@ def self.openapi_types :'operation' => :'String', :'status' => :'String', :'deploy_source' => :'String', - :'artifact_version' => :'String', :'error_message' => :'String', :'completed_at' => :'Time', :'progress' => :'DeploymentProgress', @@ -167,10 +163,6 @@ def initialize(attributes = {}) self.deploy_source = nil end - if attributes.key?(:'artifact_version') - self.artifact_version = attributes[:'artifact_version'] - end - if attributes.key?(:'error_message') self.error_message = attributes[:'error_message'] end @@ -348,7 +340,6 @@ def ==(o) operation == o.operation && status == o.status && deploy_source == o.deploy_source && - artifact_version == o.artifact_version && error_message == o.error_message && completed_at == o.completed_at && progress == o.progress && @@ -365,7 +356,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [id, project_id, resource, operation, status, deploy_source, artifact_version, error_message, completed_at, progress, created_at, updated_at].hash + [id, project_id, resource, operation, status, deploy_source, error_message, completed_at, progress, created_at, updated_at].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_deployment_summary.rb b/lib/volcano/generated/lib/volcano-generated/models/project_deployment_summary.rb index 98da112a..c334640a 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project_deployment_summary.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project_deployment_summary.rb @@ -31,7 +31,7 @@ class ProjectDeploymentSummary < ApiModelBase # Successful attempts divided by successful plus failed attempts. attr_accessor :success_rate - # Median CodeBuild duration across eligible completed attempts. + # Median build duration across eligible completed attempts. attr_accessor :median_build_duration_seconds # Attribute mapping from ruby-style variable name to JSON key. diff --git a/lib/volcano/generated/lib/volcano-generated/models/project_frontend_custom_domain.rb b/lib/volcano/generated/lib/volcano-generated/models/project_frontend_custom_domain.rb index 925bccf3..3f4852be 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/project_frontend_custom_domain.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/project_frontend_custom_domain.rb @@ -27,6 +27,9 @@ class ProjectFrontendCustomDomain < ApiModelBase attr_accessor :required_routing_record + # DNS routing target hostname for this frontend. The DNS record type depends on whether the custom domain is a zone apex. + attr_accessor :routing_target_hostname + attr_accessor :effective_urls attr_accessor :created_at @@ -66,6 +69,7 @@ def self.attribute_map :'verification_status' => :'verification_status', :'verification_records' => :'verification_records', :'required_routing_record' => :'required_routing_record', + :'routing_target_hostname' => :'routing_target_hostname', :'effective_urls' => :'effective_urls', :'created_at' => :'created_at', :'updated_at' => :'updated_at', @@ -92,6 +96,7 @@ def self.openapi_types :'verification_status' => :'String', :'verification_records' => :'Array', :'required_routing_record' => :'FrontendDomainRoutingRecord', + :'routing_target_hostname' => :'String', :'effective_urls' => :'Array', :'created_at' => :'Time', :'updated_at' => :'Time', @@ -162,6 +167,10 @@ def initialize(attributes = {}) self.required_routing_record = attributes[:'required_routing_record'] end + if attributes.key?(:'routing_target_hostname') + self.routing_target_hostname = attributes[:'routing_target_hostname'] + end + if attributes.key?(:'effective_urls') if (value = attributes[:'effective_urls']).is_a?(Array) self.effective_urls = value @@ -341,6 +350,7 @@ def ==(o) verification_status == o.verification_status && verification_records == o.verification_records && required_routing_record == o.required_routing_record && + routing_target_hostname == o.routing_target_hostname && effective_urls == o.effective_urls && created_at == o.created_at && updated_at == o.updated_at && @@ -356,7 +366,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [domain, tls_mode, domain_status, verification_status, verification_records, required_routing_record, effective_urls, created_at, updated_at, frontend].hash + [domain, tls_mode, domain_status, verification_status, verification_records, required_routing_record, routing_target_hostname, effective_urls, created_at, updated_at, frontend].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/publish_sandbox_preset_request.rb b/lib/volcano/generated/lib/volcano-generated/models/publish_sandbox_preset_request.rb new file mode 100644 index 00000000..83ad4077 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/publish_sandbox_preset_request.rb @@ -0,0 +1,268 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class PublishSandboxPresetRequest < ApiModelBase + attr_accessor :id + + attr_accessor :preset + + attr_accessor :memory_mb + + attr_accessor :deployment_id + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'preset' => :'preset', + :'memory_mb' => :'memory_mb', + :'deployment_id' => :'deployment_id' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'preset' => :'String', + :'memory_mb' => :'Integer', + :'deployment_id' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::PublishSandboxPresetRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::PublishSandboxPresetRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'preset') + self.preset = attributes[:'preset'] + else + self.preset = nil + end + + if attributes.key?(:'memory_mb') + self.memory_mb = attributes[:'memory_mb'] + else + self.memory_mb = nil + end + + if attributes.key?(:'deployment_id') + self.deployment_id = attributes[:'deployment_id'] + else + self.deployment_id = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @preset.nil? + invalid_properties.push('invalid value for "preset", preset cannot be nil.') + end + + if @memory_mb.nil? + invalid_properties.push('invalid value for "memory_mb", memory_mb cannot be nil.') + end + + if @deployment_id.nil? + invalid_properties.push('invalid value for "deployment_id", deployment_id cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @preset.nil? + preset_validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + return false unless preset_validator.valid?(@preset) + return false if @memory_mb.nil? + memory_mb_validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + return false unless memory_mb_validator.valid?(@memory_mb) + return false if @deployment_id.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] preset Object to be assigned + def preset=(preset) + validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + unless validator.valid?(preset) + fail ArgumentError, "invalid value for \"preset\", must be one of #{validator.allowable_values}." + end + @preset = preset + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] memory_mb Object to be assigned + def memory_mb=(memory_mb) + validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + unless validator.valid?(memory_mb) + fail ArgumentError, "invalid value for \"memory_mb\", must be one of #{validator.allowable_values}." + end + @memory_mb = memory_mb + end + + # Custom attribute writer method with validation + # @param [Object] deployment_id Value to be assigned + def deployment_id=(deployment_id) + if deployment_id.nil? + fail ArgumentError, 'deployment_id cannot be nil' + end + + @deployment_id = deployment_id + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + preset == o.preset && + memory_mb == o.memory_mb && + deployment_id == o.deployment_id + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, preset, memory_mb, deployment_id].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/replace_frontend_shared_variables_request.rb b/lib/volcano/generated/lib/volcano-generated/models/replace_frontend_shared_variables_request.rb new file mode 100644 index 00000000..1ebe0ff2 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/replace_frontend_shared_variables_request.rb @@ -0,0 +1,237 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class ReplaceFrontendSharedVariablesRequest < ApiModelBase + attr_accessor :frontend_shared_variables + + # When present, replace only if the current complete frontend shared list matches this list. + attr_accessor :expected_frontend_shared_variables + + # SHA-256 of the sorted unique current shared names joined by a newline. Use instead of expected_frontend_shared_variables for a compact conditional replacement. + attr_accessor :expected_frontend_shared_variables_digest + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'frontend_shared_variables' => :'frontend_shared_variables', + :'expected_frontend_shared_variables' => :'expected_frontend_shared_variables', + :'expected_frontend_shared_variables_digest' => :'expected_frontend_shared_variables_digest' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'frontend_shared_variables' => :'Array', + :'expected_frontend_shared_variables' => :'Array', + :'expected_frontend_shared_variables_digest' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::ReplaceFrontendSharedVariablesRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::ReplaceFrontendSharedVariablesRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'frontend_shared_variables') + if (value = attributes[:'frontend_shared_variables']).is_a?(Array) + self.frontend_shared_variables = value + end + else + self.frontend_shared_variables = nil + end + + if attributes.key?(:'expected_frontend_shared_variables') + if (value = attributes[:'expected_frontend_shared_variables']).is_a?(Array) + self.expected_frontend_shared_variables = value + end + end + + if attributes.key?(:'expected_frontend_shared_variables_digest') + self.expected_frontend_shared_variables_digest = attributes[:'expected_frontend_shared_variables_digest'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @frontend_shared_variables.nil? + invalid_properties.push('invalid value for "frontend_shared_variables", frontend_shared_variables cannot be nil.') + end + + if !@expected_frontend_shared_variables_digest.nil? && @expected_frontend_shared_variables_digest.to_s.length > 64 + invalid_properties.push('invalid value for "expected_frontend_shared_variables_digest", the character length must be smaller than or equal to 64.') + end + + if !@expected_frontend_shared_variables_digest.nil? && @expected_frontend_shared_variables_digest.to_s.length < 64 + invalid_properties.push('invalid value for "expected_frontend_shared_variables_digest", the character length must be greater than or equal to 64.') + end + + pattern = Regexp.new(/^[a-f0-9]{64}$/) + if !@expected_frontend_shared_variables_digest.nil? && @expected_frontend_shared_variables_digest !~ pattern + invalid_properties.push("invalid value for \"expected_frontend_shared_variables_digest\", must conform to the pattern #{pattern}.") + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @frontend_shared_variables.nil? + return false if !@expected_frontend_shared_variables_digest.nil? && @expected_frontend_shared_variables_digest.to_s.length > 64 + return false if !@expected_frontend_shared_variables_digest.nil? && @expected_frontend_shared_variables_digest.to_s.length < 64 + return false if !@expected_frontend_shared_variables_digest.nil? && @expected_frontend_shared_variables_digest !~ Regexp.new(/^[a-f0-9]{64}$/) + true + end + + # Custom attribute writer method with validation + # @param [Object] frontend_shared_variables Value to be assigned + def frontend_shared_variables=(frontend_shared_variables) + if frontend_shared_variables.nil? + fail ArgumentError, 'frontend_shared_variables cannot be nil' + end + + @frontend_shared_variables = frontend_shared_variables + end + + # Custom attribute writer method with validation + # @param [Object] expected_frontend_shared_variables Value to be assigned + def expected_frontend_shared_variables=(expected_frontend_shared_variables) + if expected_frontend_shared_variables.nil? + fail ArgumentError, 'expected_frontend_shared_variables cannot be nil' + end + + @expected_frontend_shared_variables = expected_frontend_shared_variables + end + + # Custom attribute writer method with validation + # @param [Object] expected_frontend_shared_variables_digest Value to be assigned + def expected_frontend_shared_variables_digest=(expected_frontend_shared_variables_digest) + if expected_frontend_shared_variables_digest.nil? + fail ArgumentError, 'expected_frontend_shared_variables_digest cannot be nil' + end + + if expected_frontend_shared_variables_digest.to_s.length > 64 + fail ArgumentError, 'invalid value for "expected_frontend_shared_variables_digest", the character length must be smaller than or equal to 64.' + end + + if expected_frontend_shared_variables_digest.to_s.length < 64 + fail ArgumentError, 'invalid value for "expected_frontend_shared_variables_digest", the character length must be greater than or equal to 64.' + end + + pattern = Regexp.new(/^[a-f0-9]{64}$/) + if expected_frontend_shared_variables_digest !~ pattern + fail ArgumentError, "invalid value for \"expected_frontend_shared_variables_digest\", must conform to the pattern #{pattern}." + end + + @expected_frontend_shared_variables_digest = expected_frontend_shared_variables_digest + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + frontend_shared_variables == o.frontend_shared_variables && + expected_frontend_shared_variables == o.expected_frontend_shared_variables && + expected_frontend_shared_variables_digest == o.expected_frontend_shared_variables_digest + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [frontend_shared_variables, expected_frontend_shared_variables, expected_frontend_shared_variables_digest].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/resolve_function_response.rb b/lib/volcano/generated/lib/volcano-generated/models/resolve_function_response.rb index d231ecfa..d7107e95 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/resolve_function_response.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/resolve_function_response.rb @@ -21,6 +21,9 @@ class ResolveFunctionResponse < ApiModelBase # Canonical function ID used for invocation routing attr_accessor :function_id + # Canonical HTTPS endpoint for invoking this function. Use it as-is: it does not share a domain with the API, so a host derived from the API URL will not reach the function. Omitted when the deployment serves no public invocation domain, as in local development; invoke through POST /functions/{functionId}/invoke instead. + attr_accessor :invoke_url + # Suggested SDK cache TTL for this name-to-ID mapping attr_accessor :cache_ttl_seconds @@ -29,6 +32,7 @@ def self.attribute_map { :'name' => :'name', :'function_id' => :'function_id', + :'invoke_url' => :'invoke_url', :'cache_ttl_seconds' => :'cache_ttl_seconds' } end @@ -48,6 +52,7 @@ def self.openapi_types { :'name' => :'String', :'function_id' => :'String', + :'invoke_url' => :'String', :'cache_ttl_seconds' => :'Integer' } end @@ -86,6 +91,10 @@ def initialize(attributes = {}) self.function_id = nil end + if attributes.key?(:'invoke_url') + self.invoke_url = attributes[:'invoke_url'] + end + if attributes.key?(:'cache_ttl_seconds') self.cache_ttl_seconds = attributes[:'cache_ttl_seconds'] else @@ -189,6 +198,7 @@ def ==(o) self.class == o.class && name == o.name && function_id == o.function_id && + invoke_url == o.invoke_url && cache_ttl_seconds == o.cache_ttl_seconds end @@ -201,7 +211,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [name, function_id, cache_ttl_seconds].hash + [name, function_id, invoke_url, cache_ttl_seconds].hash end # Builds the object from hash diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_access.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_access.rb new file mode 100644 index 00000000..4ae272fa --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_access.rb @@ -0,0 +1,216 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxAccess < ApiModelBase + attr_accessor :url + + attr_accessor :token + + attr_accessor :expires_at + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'url' => :'url', + :'token' => :'token', + :'expires_at' => :'expires_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'url' => :'String', + :'token' => :'String', + :'expires_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxAccess` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxAccess`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'url') + self.url = attributes[:'url'] + else + self.url = nil + end + + if attributes.key?(:'token') + self.token = attributes[:'token'] + else + self.token = nil + end + + if attributes.key?(:'expires_at') + self.expires_at = attributes[:'expires_at'] + else + self.expires_at = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @url.nil? + invalid_properties.push('invalid value for "url", url cannot be nil.') + end + + if @token.nil? + invalid_properties.push('invalid value for "token", token cannot be nil.') + end + + if @expires_at.nil? + invalid_properties.push('invalid value for "expires_at", expires_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @url.nil? + return false if @token.nil? + return false if @expires_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] url Value to be assigned + def url=(url) + if url.nil? + fail ArgumentError, 'url cannot be nil' + end + + @url = url + end + + # Custom attribute writer method with validation + # @param [Object] token Value to be assigned + def token=(token) + if token.nil? + fail ArgumentError, 'token cannot be nil' + end + + @token = token + end + + # Custom attribute writer method with validation + # @param [Object] expires_at Value to be assigned + def expires_at=(expires_at) + if expires_at.nil? + fail ArgumentError, 'expires_at cannot be nil' + end + + @expires_at = expires_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + url == o.url && + token == o.token && + expires_at == o.expires_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [url, token, expires_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_access_request.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_access_request.rb new file mode 100644 index 00000000..530c1754 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_access_request.rb @@ -0,0 +1,221 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxAccessRequest < ApiModelBase + attr_accessor :port + + attr_accessor :expires_in_seconds + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'port' => :'port', + :'expires_in_seconds' => :'expires_in_seconds' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'port' => :'Integer', + :'expires_in_seconds' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxAccessRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxAccessRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'port') + self.port = attributes[:'port'] + else + self.port = nil + end + + if attributes.key?(:'expires_in_seconds') + self.expires_in_seconds = attributes[:'expires_in_seconds'] + else + self.expires_in_seconds = 300 + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @port.nil? + invalid_properties.push('invalid value for "port", port cannot be nil.') + end + + if @port > 65532 + invalid_properties.push('invalid value for "port", must be smaller than or equal to 65532.') + end + + if @port < 1 + invalid_properties.push('invalid value for "port", must be greater than or equal to 1.') + end + + if !@expires_in_seconds.nil? && @expires_in_seconds > 300 + invalid_properties.push('invalid value for "expires_in_seconds", must be smaller than or equal to 300.') + end + + if !@expires_in_seconds.nil? && @expires_in_seconds < 1 + invalid_properties.push('invalid value for "expires_in_seconds", must be greater than or equal to 1.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @port.nil? + return false if @port > 65532 + return false if @port < 1 + return false if !@expires_in_seconds.nil? && @expires_in_seconds > 300 + return false if !@expires_in_seconds.nil? && @expires_in_seconds < 1 + true + end + + # Custom attribute writer method with validation + # @param [Object] port Value to be assigned + def port=(port) + if port.nil? + fail ArgumentError, 'port cannot be nil' + end + + if port > 65532 + fail ArgumentError, 'invalid value for "port", must be smaller than or equal to 65532.' + end + + if port < 1 + fail ArgumentError, 'invalid value for "port", must be greater than or equal to 1.' + end + + @port = port + end + + # Custom attribute writer method with validation + # @param [Object] expires_in_seconds Value to be assigned + def expires_in_seconds=(expires_in_seconds) + if expires_in_seconds.nil? + fail ArgumentError, 'expires_in_seconds cannot be nil' + end + + if expires_in_seconds > 300 + fail ArgumentError, 'invalid value for "expires_in_seconds", must be smaller than or equal to 300.' + end + + if expires_in_seconds < 1 + fail ArgumentError, 'invalid value for "expires_in_seconds", must be greater than or equal to 1.' + end + + @expires_in_seconds = expires_in_seconds + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + port == o.port && + expires_in_seconds == o.expires_in_seconds + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [port, expires_in_seconds].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity.rb new file mode 100644 index 00000000..5bf9a0d9 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity.rb @@ -0,0 +1,199 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxCapacity < ApiModelBase + attr_accessor :region + + attr_accessor :allocated_memory_mb + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'region' => :'region', + :'allocated_memory_mb' => :'allocated_memory_mb' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'region' => :'String', + :'allocated_memory_mb' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxCapacity` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxCapacity`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'region') + self.region = attributes[:'region'] + else + self.region = nil + end + + if attributes.key?(:'allocated_memory_mb') + self.allocated_memory_mb = attributes[:'allocated_memory_mb'] + else + self.allocated_memory_mb = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @region.nil? + invalid_properties.push('invalid value for "region", region cannot be nil.') + end + + if @allocated_memory_mb.nil? + invalid_properties.push('invalid value for "allocated_memory_mb", allocated_memory_mb cannot be nil.') + end + + if @allocated_memory_mb < 0 + invalid_properties.push('invalid value for "allocated_memory_mb", must be greater than or equal to 0.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @region.nil? + return false if @allocated_memory_mb.nil? + return false if @allocated_memory_mb < 0 + true + end + + # Custom attribute writer method with validation + # @param [Object] region Value to be assigned + def region=(region) + if region.nil? + fail ArgumentError, 'region cannot be nil' + end + + @region = region + end + + # Custom attribute writer method with validation + # @param [Object] allocated_memory_mb Value to be assigned + def allocated_memory_mb=(allocated_memory_mb) + if allocated_memory_mb.nil? + fail ArgumentError, 'allocated_memory_mb cannot be nil' + end + + if allocated_memory_mb < 0 + fail ArgumentError, 'invalid value for "allocated_memory_mb", must be greater than or equal to 0.' + end + + @allocated_memory_mb = allocated_memory_mb + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + region == o.region && + allocated_memory_mb == o.allocated_memory_mb + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [region, allocated_memory_mb].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity_list.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity_list.rb new file mode 100644 index 00000000..679c1a05 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_capacity_list.rb @@ -0,0 +1,166 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxCapacityList < ApiModelBase + attr_accessor :data + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxCapacityList` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxCapacityList`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_command_request.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_command_request.rb new file mode 100644 index 00000000..8462a7b7 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_command_request.rb @@ -0,0 +1,251 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxCommandRequest < ApiModelBase + attr_accessor :command + + attr_accessor :timeout_seconds + + attr_accessor :environment + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'command' => :'command', + :'timeout_seconds' => :'timeout_seconds', + :'environment' => :'environment' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'command' => :'String', + :'timeout_seconds' => :'Integer', + :'environment' => :'Hash' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxCommandRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxCommandRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'command') + self.command = attributes[:'command'] + else + self.command = nil + end + + if attributes.key?(:'timeout_seconds') + self.timeout_seconds = attributes[:'timeout_seconds'] + else + self.timeout_seconds = 60 + end + + if attributes.key?(:'environment') + if (value = attributes[:'environment']).is_a?(Hash) + self.environment = value + end + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @command.nil? + invalid_properties.push('invalid value for "command", command cannot be nil.') + end + + if @command.to_s.length > 65536 + invalid_properties.push('invalid value for "command", the character length must be smaller than or equal to 65536.') + end + + if @command.to_s.length < 1 + invalid_properties.push('invalid value for "command", the character length must be greater than or equal to 1.') + end + + if !@timeout_seconds.nil? && @timeout_seconds > 3600 + invalid_properties.push('invalid value for "timeout_seconds", must be smaller than or equal to 3600.') + end + + if !@timeout_seconds.nil? && @timeout_seconds < 1 + invalid_properties.push('invalid value for "timeout_seconds", must be greater than or equal to 1.') + end + + if !@environment.nil? && @environment.length > 64 + invalid_properties.push('invalid value for "environment", number of items must be less than or equal to 64.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @command.nil? + return false if @command.to_s.length > 65536 + return false if @command.to_s.length < 1 + return false if !@timeout_seconds.nil? && @timeout_seconds > 3600 + return false if !@timeout_seconds.nil? && @timeout_seconds < 1 + return false if !@environment.nil? && @environment.length > 64 + true + end + + # Custom attribute writer method with validation + # @param [Object] command Value to be assigned + def command=(command) + if command.nil? + fail ArgumentError, 'command cannot be nil' + end + + if command.to_s.length > 65536 + fail ArgumentError, 'invalid value for "command", the character length must be smaller than or equal to 65536.' + end + + if command.to_s.length < 1 + fail ArgumentError, 'invalid value for "command", the character length must be greater than or equal to 1.' + end + + @command = command + end + + # Custom attribute writer method with validation + # @param [Object] timeout_seconds Value to be assigned + def timeout_seconds=(timeout_seconds) + if timeout_seconds.nil? + fail ArgumentError, 'timeout_seconds cannot be nil' + end + + if timeout_seconds > 3600 + fail ArgumentError, 'invalid value for "timeout_seconds", must be smaller than or equal to 3600.' + end + + if timeout_seconds < 1 + fail ArgumentError, 'invalid value for "timeout_seconds", must be greater than or equal to 1.' + end + + @timeout_seconds = timeout_seconds + end + + # Custom attribute writer method with validation + # @param [Object] environment Value to be assigned + def environment=(environment) + if environment.nil? + fail ArgumentError, 'environment cannot be nil' + end + + if environment.length > 64 + fail ArgumentError, 'invalid value for "environment", number of items must be less than or equal to 64.' + end + + @environment = environment + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + command == o.command && + timeout_seconds == o.timeout_seconds && + environment == o.environment + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [command, timeout_seconds, environment].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_command_result.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_command_result.rb new file mode 100644 index 00000000..dffe0ebe --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_command_result.rb @@ -0,0 +1,294 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxCommandResult < ApiModelBase + attr_accessor :stdout + + attr_accessor :stderr + + attr_accessor :exit_code + + attr_accessor :stdout_truncated + + attr_accessor :stderr_truncated + + attr_accessor :timed_out + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'stdout' => :'stdout', + :'stderr' => :'stderr', + :'exit_code' => :'exit_code', + :'stdout_truncated' => :'stdout_truncated', + :'stderr_truncated' => :'stderr_truncated', + :'timed_out' => :'timed_out' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'stdout' => :'String', + :'stderr' => :'String', + :'exit_code' => :'Integer', + :'stdout_truncated' => :'Boolean', + :'stderr_truncated' => :'Boolean', + :'timed_out' => :'Boolean' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxCommandResult` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxCommandResult`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'stdout') + self.stdout = attributes[:'stdout'] + else + self.stdout = nil + end + + if attributes.key?(:'stderr') + self.stderr = attributes[:'stderr'] + else + self.stderr = nil + end + + if attributes.key?(:'exit_code') + self.exit_code = attributes[:'exit_code'] + else + self.exit_code = nil + end + + if attributes.key?(:'stdout_truncated') + self.stdout_truncated = attributes[:'stdout_truncated'] + else + self.stdout_truncated = nil + end + + if attributes.key?(:'stderr_truncated') + self.stderr_truncated = attributes[:'stderr_truncated'] + else + self.stderr_truncated = nil + end + + if attributes.key?(:'timed_out') + self.timed_out = attributes[:'timed_out'] + else + self.timed_out = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @stdout.nil? + invalid_properties.push('invalid value for "stdout", stdout cannot be nil.') + end + + if @stderr.nil? + invalid_properties.push('invalid value for "stderr", stderr cannot be nil.') + end + + if @exit_code.nil? + invalid_properties.push('invalid value for "exit_code", exit_code cannot be nil.') + end + + if @stdout_truncated.nil? + invalid_properties.push('invalid value for "stdout_truncated", stdout_truncated cannot be nil.') + end + + if @stderr_truncated.nil? + invalid_properties.push('invalid value for "stderr_truncated", stderr_truncated cannot be nil.') + end + + if @timed_out.nil? + invalid_properties.push('invalid value for "timed_out", timed_out cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @stdout.nil? + return false if @stderr.nil? + return false if @exit_code.nil? + return false if @stdout_truncated.nil? + return false if @stderr_truncated.nil? + return false if @timed_out.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] stdout Value to be assigned + def stdout=(stdout) + if stdout.nil? + fail ArgumentError, 'stdout cannot be nil' + end + + @stdout = stdout + end + + # Custom attribute writer method with validation + # @param [Object] stderr Value to be assigned + def stderr=(stderr) + if stderr.nil? + fail ArgumentError, 'stderr cannot be nil' + end + + @stderr = stderr + end + + # Custom attribute writer method with validation + # @param [Object] exit_code Value to be assigned + def exit_code=(exit_code) + if exit_code.nil? + fail ArgumentError, 'exit_code cannot be nil' + end + + @exit_code = exit_code + end + + # Custom attribute writer method with validation + # @param [Object] stdout_truncated Value to be assigned + def stdout_truncated=(stdout_truncated) + if stdout_truncated.nil? + fail ArgumentError, 'stdout_truncated cannot be nil' + end + + @stdout_truncated = stdout_truncated + end + + # Custom attribute writer method with validation + # @param [Object] stderr_truncated Value to be assigned + def stderr_truncated=(stderr_truncated) + if stderr_truncated.nil? + fail ArgumentError, 'stderr_truncated cannot be nil' + end + + @stderr_truncated = stderr_truncated + end + + # Custom attribute writer method with validation + # @param [Object] timed_out Value to be assigned + def timed_out=(timed_out) + if timed_out.nil? + fail ArgumentError, 'timed_out cannot be nil' + end + + @timed_out = timed_out + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + stdout == o.stdout && + stderr == o.stderr && + exit_code == o.exit_code && + stdout_truncated == o.stdout_truncated && + stderr_truncated == o.stderr_truncated && + timed_out == o.timed_out + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [stdout, stderr, exit_code, stdout_truncated, stderr_truncated, timed_out].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment.rb new file mode 100644 index 00000000..6e7aefb2 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment.rb @@ -0,0 +1,242 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxDeployment < ApiModelBase + attr_accessor :id + + attr_accessor :status + + attr_accessor :created_at + + attr_accessor :updated_at + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'status' => :'status', + :'created_at' => :'created_at', + :'updated_at' => :'updated_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'status' => :'String', + :'created_at' => :'Time', + :'updated_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxDeployment` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxDeployment`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'status') + self.status = attributes[:'status'] + else + self.status = nil + end + + if attributes.key?(:'created_at') + self.created_at = attributes[:'created_at'] + else + self.created_at = nil + end + + if attributes.key?(:'updated_at') + self.updated_at = attributes[:'updated_at'] + else + self.updated_at = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @status.nil? + invalid_properties.push('invalid value for "status", status cannot be nil.') + end + + if @created_at.nil? + invalid_properties.push('invalid value for "created_at", created_at cannot be nil.') + end + + if @updated_at.nil? + invalid_properties.push('invalid value for "updated_at", updated_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @status.nil? + return false if @created_at.nil? + return false if @updated_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method with validation + # @param [Object] status Value to be assigned + def status=(status) + if status.nil? + fail ArgumentError, 'status cannot be nil' + end + + @status = status + end + + # Custom attribute writer method with validation + # @param [Object] created_at Value to be assigned + def created_at=(created_at) + if created_at.nil? + fail ArgumentError, 'created_at cannot be nil' + end + + @created_at = created_at + end + + # Custom attribute writer method with validation + # @param [Object] updated_at Value to be assigned + def updated_at=(updated_at) + if updated_at.nil? + fail ArgumentError, 'updated_at cannot be nil' + end + + @updated_at = updated_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + status == o.status && + created_at == o.created_at && + updated_at == o.updated_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, status, created_at, updated_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment_page.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment_page.rb new file mode 100644 index 00000000..31a9afaf --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_deployment_page.rb @@ -0,0 +1,192 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxDeploymentPage < ApiModelBase + attr_accessor :data + + attr_accessor :pagination + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data', + :'pagination' => :'pagination' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array', + :'pagination' => :'SandboxPagination' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxDeploymentPage` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxDeploymentPage`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + + if attributes.key?(:'pagination') + self.pagination = attributes[:'pagination'] + else + self.pagination = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + if @pagination.nil? + invalid_properties.push('invalid value for "pagination", pagination cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + return false if @pagination.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Custom attribute writer method with validation + # @param [Object] pagination Value to be assigned + def pagination=(pagination) + if pagination.nil? + fail ArgumentError, 'pagination cannot be nil' + end + + @pagination = pagination + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data && + pagination == o.pagination + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data, pagination].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_request.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_request.rb new file mode 100644 index 00000000..c5367c86 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_request.rb @@ -0,0 +1,340 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxExecutionRequest < ApiModelBase + attr_accessor :preset + + attr_accessor :sandbox_id + + attr_accessor :memory_mb + + # Region such as `us-east-1`. Region IDs issued by earlier versions of the API are still accepted. + attr_accessor :region + + attr_accessor :command + + attr_accessor :timeout_seconds + + attr_accessor :environment + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'preset' => :'preset', + :'sandbox_id' => :'sandbox_id', + :'memory_mb' => :'memory_mb', + :'region' => :'region', + :'command' => :'command', + :'timeout_seconds' => :'timeout_seconds', + :'environment' => :'environment' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'preset' => :'String', + :'sandbox_id' => :'String', + :'memory_mb' => :'Integer', + :'region' => :'String', + :'command' => :'String', + :'timeout_seconds' => :'Integer', + :'environment' => :'Hash' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxExecutionRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxExecutionRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'preset') + self.preset = attributes[:'preset'] + end + + if attributes.key?(:'sandbox_id') + self.sandbox_id = attributes[:'sandbox_id'] + end + + if attributes.key?(:'memory_mb') + self.memory_mb = attributes[:'memory_mb'] + end + + if attributes.key?(:'region') + self.region = attributes[:'region'] + else + self.region = nil + end + + if attributes.key?(:'command') + self.command = attributes[:'command'] + else + self.command = nil + end + + if attributes.key?(:'timeout_seconds') + self.timeout_seconds = attributes[:'timeout_seconds'] + else + self.timeout_seconds = 60 + end + + if attributes.key?(:'environment') + if (value = attributes[:'environment']).is_a?(Hash) + self.environment = value + end + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @region.nil? + invalid_properties.push('invalid value for "region", region cannot be nil.') + end + + pattern = Regexp.new(/^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$/) + if @region !~ pattern + invalid_properties.push("invalid value for \"region\", must conform to the pattern #{pattern}.") + end + + if @command.nil? + invalid_properties.push('invalid value for "command", command cannot be nil.') + end + + if @command.to_s.length > 65536 + invalid_properties.push('invalid value for "command", the character length must be smaller than or equal to 65536.') + end + + if @command.to_s.length < 1 + invalid_properties.push('invalid value for "command", the character length must be greater than or equal to 1.') + end + + if !@timeout_seconds.nil? && @timeout_seconds > 60 + invalid_properties.push('invalid value for "timeout_seconds", must be smaller than or equal to 60.') + end + + if !@timeout_seconds.nil? && @timeout_seconds < 1 + invalid_properties.push('invalid value for "timeout_seconds", must be greater than or equal to 1.') + end + + if !@environment.nil? && @environment.length > 64 + invalid_properties.push('invalid value for "environment", number of items must be less than or equal to 64.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + preset_validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + return false unless preset_validator.valid?(@preset) + memory_mb_validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + return false unless memory_mb_validator.valid?(@memory_mb) + return false if @region.nil? + return false if @region !~ Regexp.new(/^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$/) + return false if @command.nil? + return false if @command.to_s.length > 65536 + return false if @command.to_s.length < 1 + return false if !@timeout_seconds.nil? && @timeout_seconds > 60 + return false if !@timeout_seconds.nil? && @timeout_seconds < 1 + return false if !@environment.nil? && @environment.length > 64 + true + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] preset Object to be assigned + def preset=(preset) + validator = EnumAttributeValidator.new('String', ["python3.12", "node22"]) + unless validator.valid?(preset) + fail ArgumentError, "invalid value for \"preset\", must be one of #{validator.allowable_values}." + end + @preset = preset + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] memory_mb Object to be assigned + def memory_mb=(memory_mb) + validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + unless validator.valid?(memory_mb) + fail ArgumentError, "invalid value for \"memory_mb\", must be one of #{validator.allowable_values}." + end + @memory_mb = memory_mb + end + + # Custom attribute writer method with validation + # @param [Object] region Value to be assigned + def region=(region) + if region.nil? + fail ArgumentError, 'region cannot be nil' + end + + pattern = Regexp.new(/^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$/) + if region !~ pattern + fail ArgumentError, "invalid value for \"region\", must conform to the pattern #{pattern}." + end + + @region = region + end + + # Custom attribute writer method with validation + # @param [Object] command Value to be assigned + def command=(command) + if command.nil? + fail ArgumentError, 'command cannot be nil' + end + + if command.to_s.length > 65536 + fail ArgumentError, 'invalid value for "command", the character length must be smaller than or equal to 65536.' + end + + if command.to_s.length < 1 + fail ArgumentError, 'invalid value for "command", the character length must be greater than or equal to 1.' + end + + @command = command + end + + # Custom attribute writer method with validation + # @param [Object] timeout_seconds Value to be assigned + def timeout_seconds=(timeout_seconds) + if timeout_seconds.nil? + fail ArgumentError, 'timeout_seconds cannot be nil' + end + + if timeout_seconds > 60 + fail ArgumentError, 'invalid value for "timeout_seconds", must be smaller than or equal to 60.' + end + + if timeout_seconds < 1 + fail ArgumentError, 'invalid value for "timeout_seconds", must be greater than or equal to 1.' + end + + @timeout_seconds = timeout_seconds + end + + # Custom attribute writer method with validation + # @param [Object] environment Value to be assigned + def environment=(environment) + if environment.nil? + fail ArgumentError, 'environment cannot be nil' + end + + if environment.length > 64 + fail ArgumentError, 'invalid value for "environment", number of items must be less than or equal to 64.' + end + + @environment = environment + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + preset == o.preset && + sandbox_id == o.sandbox_id && + memory_mb == o.memory_mb && + region == o.region && + command == o.command && + timeout_seconds == o.timeout_seconds && + environment == o.environment + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [preset, sandbox_id, memory_mb, region, command, timeout_seconds, environment].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_result.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_result.rb new file mode 100644 index 00000000..2c2bd216 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_execution_result.rb @@ -0,0 +1,381 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxExecutionResult < ApiModelBase + attr_accessor :stdout + + attr_accessor :stderr + + attr_accessor :exit_code + + attr_accessor :stdout_truncated + + attr_accessor :stderr_truncated + + attr_accessor :timed_out + + attr_accessor :session_id + + attr_accessor :region + + attr_accessor :duration_ms + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'stdout' => :'stdout', + :'stderr' => :'stderr', + :'exit_code' => :'exit_code', + :'stdout_truncated' => :'stdout_truncated', + :'stderr_truncated' => :'stderr_truncated', + :'timed_out' => :'timed_out', + :'session_id' => :'session_id', + :'region' => :'region', + :'duration_ms' => :'duration_ms' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'stdout' => :'String', + :'stderr' => :'String', + :'exit_code' => :'Integer', + :'stdout_truncated' => :'Boolean', + :'stderr_truncated' => :'Boolean', + :'timed_out' => :'Boolean', + :'session_id' => :'String', + :'region' => :'String', + :'duration_ms' => :'Integer' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxExecutionResult` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxExecutionResult`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'stdout') + self.stdout = attributes[:'stdout'] + else + self.stdout = nil + end + + if attributes.key?(:'stderr') + self.stderr = attributes[:'stderr'] + else + self.stderr = nil + end + + if attributes.key?(:'exit_code') + self.exit_code = attributes[:'exit_code'] + else + self.exit_code = nil + end + + if attributes.key?(:'stdout_truncated') + self.stdout_truncated = attributes[:'stdout_truncated'] + else + self.stdout_truncated = nil + end + + if attributes.key?(:'stderr_truncated') + self.stderr_truncated = attributes[:'stderr_truncated'] + else + self.stderr_truncated = nil + end + + if attributes.key?(:'timed_out') + self.timed_out = attributes[:'timed_out'] + else + self.timed_out = nil + end + + if attributes.key?(:'session_id') + self.session_id = attributes[:'session_id'] + else + self.session_id = nil + end + + if attributes.key?(:'region') + self.region = attributes[:'region'] + else + self.region = nil + end + + if attributes.key?(:'duration_ms') + self.duration_ms = attributes[:'duration_ms'] + else + self.duration_ms = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @stdout.nil? + invalid_properties.push('invalid value for "stdout", stdout cannot be nil.') + end + + if @stderr.nil? + invalid_properties.push('invalid value for "stderr", stderr cannot be nil.') + end + + if @exit_code.nil? + invalid_properties.push('invalid value for "exit_code", exit_code cannot be nil.') + end + + if @stdout_truncated.nil? + invalid_properties.push('invalid value for "stdout_truncated", stdout_truncated cannot be nil.') + end + + if @stderr_truncated.nil? + invalid_properties.push('invalid value for "stderr_truncated", stderr_truncated cannot be nil.') + end + + if @timed_out.nil? + invalid_properties.push('invalid value for "timed_out", timed_out cannot be nil.') + end + + if @session_id.nil? + invalid_properties.push('invalid value for "session_id", session_id cannot be nil.') + end + + if @region.nil? + invalid_properties.push('invalid value for "region", region cannot be nil.') + end + + if @duration_ms.nil? + invalid_properties.push('invalid value for "duration_ms", duration_ms cannot be nil.') + end + + if @duration_ms < 0 + invalid_properties.push('invalid value for "duration_ms", must be greater than or equal to 0.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @stdout.nil? + return false if @stderr.nil? + return false if @exit_code.nil? + return false if @stdout_truncated.nil? + return false if @stderr_truncated.nil? + return false if @timed_out.nil? + return false if @session_id.nil? + return false if @region.nil? + return false if @duration_ms.nil? + return false if @duration_ms < 0 + true + end + + # Custom attribute writer method with validation + # @param [Object] stdout Value to be assigned + def stdout=(stdout) + if stdout.nil? + fail ArgumentError, 'stdout cannot be nil' + end + + @stdout = stdout + end + + # Custom attribute writer method with validation + # @param [Object] stderr Value to be assigned + def stderr=(stderr) + if stderr.nil? + fail ArgumentError, 'stderr cannot be nil' + end + + @stderr = stderr + end + + # Custom attribute writer method with validation + # @param [Object] exit_code Value to be assigned + def exit_code=(exit_code) + if exit_code.nil? + fail ArgumentError, 'exit_code cannot be nil' + end + + @exit_code = exit_code + end + + # Custom attribute writer method with validation + # @param [Object] stdout_truncated Value to be assigned + def stdout_truncated=(stdout_truncated) + if stdout_truncated.nil? + fail ArgumentError, 'stdout_truncated cannot be nil' + end + + @stdout_truncated = stdout_truncated + end + + # Custom attribute writer method with validation + # @param [Object] stderr_truncated Value to be assigned + def stderr_truncated=(stderr_truncated) + if stderr_truncated.nil? + fail ArgumentError, 'stderr_truncated cannot be nil' + end + + @stderr_truncated = stderr_truncated + end + + # Custom attribute writer method with validation + # @param [Object] timed_out Value to be assigned + def timed_out=(timed_out) + if timed_out.nil? + fail ArgumentError, 'timed_out cannot be nil' + end + + @timed_out = timed_out + end + + # Custom attribute writer method with validation + # @param [Object] session_id Value to be assigned + def session_id=(session_id) + if session_id.nil? + fail ArgumentError, 'session_id cannot be nil' + end + + @session_id = session_id + end + + # Custom attribute writer method with validation + # @param [Object] region Value to be assigned + def region=(region) + if region.nil? + fail ArgumentError, 'region cannot be nil' + end + + @region = region + end + + # Custom attribute writer method with validation + # @param [Object] duration_ms Value to be assigned + def duration_ms=(duration_ms) + if duration_ms.nil? + fail ArgumentError, 'duration_ms cannot be nil' + end + + if duration_ms < 0 + fail ArgumentError, 'invalid value for "duration_ms", must be greater than or equal to 0.' + end + + @duration_ms = duration_ms + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + stdout == o.stdout && + stderr == o.stderr && + exit_code == o.exit_code && + stdout_truncated == o.stdout_truncated && + stderr_truncated == o.stderr_truncated && + timed_out == o.timed_out && + session_id == o.session_id && + region == o.region && + duration_ms == o.duration_ms + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [stdout, stderr, exit_code, stdout_truncated, stderr_truncated, timed_out, session_id, region, duration_ms].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_read_request.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_read_request.rb new file mode 100644 index 00000000..5323ce7f --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_read_request.rb @@ -0,0 +1,182 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxFileReadRequest < ApiModelBase + attr_accessor :path + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'path' => :'path' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'path' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxFileReadRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxFileReadRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'path') + self.path = attributes[:'path'] + else + self.path = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @path.nil? + invalid_properties.push('invalid value for "path", path cannot be nil.') + end + + if @path.to_s.length > 4096 + invalid_properties.push('invalid value for "path", the character length must be smaller than or equal to 4096.') + end + + if @path.to_s.length < 1 + invalid_properties.push('invalid value for "path", the character length must be greater than or equal to 1.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @path.nil? + return false if @path.to_s.length > 4096 + return false if @path.to_s.length < 1 + true + end + + # Custom attribute writer method with validation + # @param [Object] path Value to be assigned + def path=(path) + if path.nil? + fail ArgumentError, 'path cannot be nil' + end + + if path.to_s.length > 4096 + fail ArgumentError, 'invalid value for "path", the character length must be smaller than or equal to 4096.' + end + + if path.to_s.length < 1 + fail ArgumentError, 'invalid value for "path", the character length must be greater than or equal to 1.' + end + + @path = path + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + path == o.path + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [path].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_result.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_result.rb new file mode 100644 index 00000000..18af717c --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_result.rb @@ -0,0 +1,164 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxFileResult < ApiModelBase + attr_accessor :data + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxFileResult` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxFileResult`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + self.data = attributes[:'data'] + else + self.data = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_write_request.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_write_request.rb new file mode 100644 index 00000000..67f64edc --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_file_write_request.rb @@ -0,0 +1,217 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxFileWriteRequest < ApiModelBase + attr_accessor :path + + attr_accessor :data + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'path' => :'path', + :'data' => :'data' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'path' => :'String', + :'data' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxFileWriteRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxFileWriteRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'path') + self.path = attributes[:'path'] + else + self.path = nil + end + + if attributes.key?(:'data') + self.data = attributes[:'data'] + else + self.data = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @path.nil? + invalid_properties.push('invalid value for "path", path cannot be nil.') + end + + if @path.to_s.length > 4096 + invalid_properties.push('invalid value for "path", the character length must be smaller than or equal to 4096.') + end + + if @path.to_s.length < 1 + invalid_properties.push('invalid value for "path", the character length must be greater than or equal to 1.') + end + + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + if @data.to_s.length > 11184812 + invalid_properties.push('invalid value for "data", the character length must be smaller than or equal to 11184812.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @path.nil? + return false if @path.to_s.length > 4096 + return false if @path.to_s.length < 1 + return false if @data.nil? + return false if @data.to_s.length > 11184812 + true + end + + # Custom attribute writer method with validation + # @param [Object] path Value to be assigned + def path=(path) + if path.nil? + fail ArgumentError, 'path cannot be nil' + end + + if path.to_s.length > 4096 + fail ArgumentError, 'invalid value for "path", the character length must be smaller than or equal to 4096.' + end + + if path.to_s.length < 1 + fail ArgumentError, 'invalid value for "path", the character length must be greater than or equal to 1.' + end + + @path = path + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + if data.to_s.length > 11184812 + fail ArgumentError, 'invalid value for "data", the character length must be smaller than or equal to 11184812.' + end + + @data = data + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + path == o.path && + data == o.data + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [path, data].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_pagination.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_pagination.rb new file mode 100644 index 00000000..9a40e575 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_pagination.rb @@ -0,0 +1,199 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxPagination < ApiModelBase + attr_accessor :limit + + attr_accessor :has_more + + attr_accessor :next_cursor + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'limit' => :'limit', + :'has_more' => :'has_more', + :'next_cursor' => :'next_cursor' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'limit' => :'Integer', + :'has_more' => :'Boolean', + :'next_cursor' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxPagination` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxPagination`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'limit') + self.limit = attributes[:'limit'] + else + self.limit = nil + end + + if attributes.key?(:'has_more') + self.has_more = attributes[:'has_more'] + else + self.has_more = nil + end + + if attributes.key?(:'next_cursor') + self.next_cursor = attributes[:'next_cursor'] + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @limit.nil? + invalid_properties.push('invalid value for "limit", limit cannot be nil.') + end + + if @has_more.nil? + invalid_properties.push('invalid value for "has_more", has_more cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @limit.nil? + return false if @has_more.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] limit Value to be assigned + def limit=(limit) + if limit.nil? + fail ArgumentError, 'limit cannot be nil' + end + + @limit = limit + end + + # Custom attribute writer method with validation + # @param [Object] has_more Value to be assigned + def has_more=(has_more) + if has_more.nil? + fail ArgumentError, 'has_more cannot be nil' + end + + @has_more = has_more + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + limit == o.limit && + has_more == o.has_more && + next_cursor == o.next_cursor + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [limit, has_more, next_cursor].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_preset.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_preset.rb new file mode 100644 index 00000000..91316a27 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_preset.rb @@ -0,0 +1,294 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxPreset < ApiModelBase + attr_accessor :id + + attr_accessor :runtime + + attr_accessor :version + + attr_accessor :memory_mb + + attr_accessor :regions + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'runtime' => :'runtime', + :'version' => :'version', + :'memory_mb' => :'memory_mb', + :'regions' => :'regions' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'runtime' => :'String', + :'version' => :'String', + :'memory_mb' => :'Integer', + :'regions' => :'Array' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxPreset` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxPreset`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'runtime') + self.runtime = attributes[:'runtime'] + else + self.runtime = nil + end + + if attributes.key?(:'version') + self.version = attributes[:'version'] + else + self.version = nil + end + + if attributes.key?(:'memory_mb') + self.memory_mb = attributes[:'memory_mb'] + else + self.memory_mb = nil + end + + if attributes.key?(:'regions') + if (value = attributes[:'regions']).is_a?(Array) + self.regions = value + end + else + self.regions = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @runtime.nil? + invalid_properties.push('invalid value for "runtime", runtime cannot be nil.') + end + + if @version.nil? + invalid_properties.push('invalid value for "version", version cannot be nil.') + end + + if @memory_mb.nil? + invalid_properties.push('invalid value for "memory_mb", memory_mb cannot be nil.') + end + + if @regions.nil? + invalid_properties.push('invalid value for "regions", regions cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @runtime.nil? + return false if @version.nil? + return false if @memory_mb.nil? + memory_mb_validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + return false unless memory_mb_validator.valid?(@memory_mb) + return false if @regions.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method with validation + # @param [Object] runtime Value to be assigned + def runtime=(runtime) + if runtime.nil? + fail ArgumentError, 'runtime cannot be nil' + end + + @runtime = runtime + end + + # Custom attribute writer method with validation + # @param [Object] version Value to be assigned + def version=(version) + if version.nil? + fail ArgumentError, 'version cannot be nil' + end + + @version = version + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] memory_mb Object to be assigned + def memory_mb=(memory_mb) + validator = EnumAttributeValidator.new('Integer', [1024, 2048]) + unless validator.valid?(memory_mb) + fail ArgumentError, "invalid value for \"memory_mb\", must be one of #{validator.allowable_values}." + end + @memory_mb = memory_mb + end + + # Custom attribute writer method with validation + # @param [Object] regions Value to be assigned + def regions=(regions) + if regions.nil? + fail ArgumentError, 'regions cannot be nil' + end + + @regions = regions + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + runtime == o.runtime && + version == o.version && + memory_mb == o.memory_mb && + regions == o.regions + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, runtime, version, memory_mb, regions].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_preset_list.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_preset_list.rb new file mode 100644 index 00000000..b2e12396 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_preset_list.rb @@ -0,0 +1,166 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxPresetList < ApiModelBase + attr_accessor :data + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxPresetList` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxPresetList`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_session.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_session.rb new file mode 100644 index 00000000..42cafbc0 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_session.rb @@ -0,0 +1,407 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxSession < ApiModelBase + attr_accessor :id + + attr_accessor :project_id + + attr_accessor :sandbox_id + + attr_accessor :state + + attr_accessor :desired_state + + attr_accessor :region + + attr_accessor :memory_mb + + attr_accessor :created_at + + attr_accessor :started_at + + attr_accessor :expires_at + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'project_id' => :'project_id', + :'sandbox_id' => :'sandbox_id', + :'state' => :'state', + :'desired_state' => :'desired_state', + :'region' => :'region', + :'memory_mb' => :'memory_mb', + :'created_at' => :'created_at', + :'started_at' => :'started_at', + :'expires_at' => :'expires_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'project_id' => :'String', + :'sandbox_id' => :'String', + :'state' => :'String', + :'desired_state' => :'String', + :'region' => :'String', + :'memory_mb' => :'Integer', + :'created_at' => :'Time', + :'started_at' => :'Time', + :'expires_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxSession` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxSession`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'project_id') + self.project_id = attributes[:'project_id'] + else + self.project_id = nil + end + + if attributes.key?(:'sandbox_id') + self.sandbox_id = attributes[:'sandbox_id'] + else + self.sandbox_id = nil + end + + if attributes.key?(:'state') + self.state = attributes[:'state'] + else + self.state = nil + end + + if attributes.key?(:'desired_state') + self.desired_state = attributes[:'desired_state'] + else + self.desired_state = nil + end + + if attributes.key?(:'region') + self.region = attributes[:'region'] + else + self.region = nil + end + + if attributes.key?(:'memory_mb') + self.memory_mb = attributes[:'memory_mb'] + else + self.memory_mb = nil + end + + if attributes.key?(:'created_at') + self.created_at = attributes[:'created_at'] + else + self.created_at = nil + end + + if attributes.key?(:'started_at') + self.started_at = attributes[:'started_at'] + end + + if attributes.key?(:'expires_at') + self.expires_at = attributes[:'expires_at'] + else + self.expires_at = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @project_id.nil? + invalid_properties.push('invalid value for "project_id", project_id cannot be nil.') + end + + if @sandbox_id.nil? + invalid_properties.push('invalid value for "sandbox_id", sandbox_id cannot be nil.') + end + + if @state.nil? + invalid_properties.push('invalid value for "state", state cannot be nil.') + end + + if @desired_state.nil? + invalid_properties.push('invalid value for "desired_state", desired_state cannot be nil.') + end + + if @region.nil? + invalid_properties.push('invalid value for "region", region cannot be nil.') + end + + if @memory_mb.nil? + invalid_properties.push('invalid value for "memory_mb", memory_mb cannot be nil.') + end + + if @created_at.nil? + invalid_properties.push('invalid value for "created_at", created_at cannot be nil.') + end + + if @expires_at.nil? + invalid_properties.push('invalid value for "expires_at", expires_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @project_id.nil? + return false if @sandbox_id.nil? + return false if @state.nil? + state_validator = EnumAttributeValidator.new('String', ["starting", "running", "suspending", "suspended", "resuming", "terminating", "terminated", "unknown"]) + return false unless state_validator.valid?(@state) + return false if @desired_state.nil? + desired_state_validator = EnumAttributeValidator.new('String', ["running", "suspended", "terminated"]) + return false unless desired_state_validator.valid?(@desired_state) + return false if @region.nil? + return false if @memory_mb.nil? + return false if @created_at.nil? + return false if @expires_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method with validation + # @param [Object] project_id Value to be assigned + def project_id=(project_id) + if project_id.nil? + fail ArgumentError, 'project_id cannot be nil' + end + + @project_id = project_id + end + + # Custom attribute writer method with validation + # @param [Object] sandbox_id Value to be assigned + def sandbox_id=(sandbox_id) + if sandbox_id.nil? + fail ArgumentError, 'sandbox_id cannot be nil' + end + + @sandbox_id = sandbox_id + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] state Object to be assigned + def state=(state) + validator = EnumAttributeValidator.new('String', ["starting", "running", "suspending", "suspended", "resuming", "terminating", "terminated", "unknown"]) + unless validator.valid?(state) + fail ArgumentError, "invalid value for \"state\", must be one of #{validator.allowable_values}." + end + @state = state + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] desired_state Object to be assigned + def desired_state=(desired_state) + validator = EnumAttributeValidator.new('String', ["running", "suspended", "terminated"]) + unless validator.valid?(desired_state) + fail ArgumentError, "invalid value for \"desired_state\", must be one of #{validator.allowable_values}." + end + @desired_state = desired_state + end + + # Custom attribute writer method with validation + # @param [Object] region Value to be assigned + def region=(region) + if region.nil? + fail ArgumentError, 'region cannot be nil' + end + + @region = region + end + + # Custom attribute writer method with validation + # @param [Object] memory_mb Value to be assigned + def memory_mb=(memory_mb) + if memory_mb.nil? + fail ArgumentError, 'memory_mb cannot be nil' + end + + @memory_mb = memory_mb + end + + # Custom attribute writer method with validation + # @param [Object] created_at Value to be assigned + def created_at=(created_at) + if created_at.nil? + fail ArgumentError, 'created_at cannot be nil' + end + + @created_at = created_at + end + + # Custom attribute writer method with validation + # @param [Object] expires_at Value to be assigned + def expires_at=(expires_at) + if expires_at.nil? + fail ArgumentError, 'expires_at cannot be nil' + end + + @expires_at = expires_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + project_id == o.project_id && + sandbox_id == o.sandbox_id && + state == o.state && + desired_state == o.desired_state && + region == o.region && + memory_mb == o.memory_mb && + created_at == o.created_at && + started_at == o.started_at && + expires_at == o.expires_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, project_id, sandbox_id, state, desired_state, region, memory_mb, created_at, started_at, expires_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_session_page.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_session_page.rb new file mode 100644 index 00000000..4f1cb30f --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_session_page.rb @@ -0,0 +1,192 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxSessionPage < ApiModelBase + attr_accessor :data + + attr_accessor :pagination + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data', + :'pagination' => :'pagination' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array', + :'pagination' => :'SandboxPagination' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxSessionPage` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxSessionPage`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + + if attributes.key?(:'pagination') + self.pagination = attributes[:'pagination'] + else + self.pagination = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + if @pagination.nil? + invalid_properties.push('invalid value for "pagination", pagination cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + return false if @pagination.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Custom attribute writer method with validation + # @param [Object] pagination Value to be assigned + def pagination=(pagination) + if pagination.nil? + fail ArgumentError, 'pagination cannot be nil' + end + + @pagination = pagination + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data && + pagination == o.pagination + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data, pagination].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_subject_grant_request.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_subject_grant_request.rb new file mode 100644 index 00000000..d22a2b37 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_subject_grant_request.rb @@ -0,0 +1,164 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxSubjectGrantRequest < ApiModelBase + attr_accessor :expires_at + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'expires_at' => :'expires_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'expires_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxSubjectGrantRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxSubjectGrantRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'expires_at') + self.expires_at = attributes[:'expires_at'] + else + self.expires_at = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @expires_at.nil? + invalid_properties.push('invalid value for "expires_at", expires_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @expires_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] expires_at Value to be assigned + def expires_at=(expires_at) + if expires_at.nil? + fail ArgumentError, 'expires_at cannot be nil' + end + + @expires_at = expires_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + expires_at == o.expires_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [expires_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_template.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_template.rb new file mode 100644 index 00000000..db4e7d4f --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_template.rb @@ -0,0 +1,321 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxTemplate < ApiModelBase + attr_accessor :id + + attr_accessor :project_id + + attr_accessor :name + + attr_accessor :preset + + attr_accessor :memory_mb + + attr_accessor :status + + attr_accessor :created_at + + class EnumAttributeValidator + attr_reader :datatype + attr_reader :allowable_values + + def initialize(datatype, allowable_values) + @allowable_values = allowable_values.map do |value| + case datatype.to_s + when /Integer/i + value.to_i + when /Float/i + value.to_f + else + value + end + end + end + + def valid?(value) + !value || allowable_values.include?(value) + end + end + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'id' => :'id', + :'project_id' => :'project_id', + :'name' => :'name', + :'preset' => :'preset', + :'memory_mb' => :'memory_mb', + :'status' => :'status', + :'created_at' => :'created_at' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'id' => :'String', + :'project_id' => :'String', + :'name' => :'String', + :'preset' => :'String', + :'memory_mb' => :'Integer', + :'status' => :'String', + :'created_at' => :'Time' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxTemplate` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxTemplate`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'id') + self.id = attributes[:'id'] + else + self.id = nil + end + + if attributes.key?(:'project_id') + self.project_id = attributes[:'project_id'] + else + self.project_id = nil + end + + if attributes.key?(:'name') + self.name = attributes[:'name'] + else + self.name = nil + end + + if attributes.key?(:'preset') + self.preset = attributes[:'preset'] + end + + if attributes.key?(:'memory_mb') + self.memory_mb = attributes[:'memory_mb'] + end + + if attributes.key?(:'status') + self.status = attributes[:'status'] + else + self.status = nil + end + + if attributes.key?(:'created_at') + self.created_at = attributes[:'created_at'] + else + self.created_at = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @id.nil? + invalid_properties.push('invalid value for "id", id cannot be nil.') + end + + if @project_id.nil? + invalid_properties.push('invalid value for "project_id", project_id cannot be nil.') + end + + if @name.nil? + invalid_properties.push('invalid value for "name", name cannot be nil.') + end + + pattern = Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + if @name !~ pattern + invalid_properties.push("invalid value for \"name\", must conform to the pattern #{pattern}.") + end + + if @status.nil? + invalid_properties.push('invalid value for "status", status cannot be nil.') + end + + if @created_at.nil? + invalid_properties.push('invalid value for "created_at", created_at cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @id.nil? + return false if @project_id.nil? + return false if @name.nil? + return false if @name !~ Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + return false if @status.nil? + status_validator = EnumAttributeValidator.new('String', ["ready", "unavailable", "deleting"]) + return false unless status_validator.valid?(@status) + return false if @created_at.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] id Value to be assigned + def id=(id) + if id.nil? + fail ArgumentError, 'id cannot be nil' + end + + @id = id + end + + # Custom attribute writer method with validation + # @param [Object] project_id Value to be assigned + def project_id=(project_id) + if project_id.nil? + fail ArgumentError, 'project_id cannot be nil' + end + + @project_id = project_id + end + + # Custom attribute writer method with validation + # @param [Object] name Value to be assigned + def name=(name) + if name.nil? + fail ArgumentError, 'name cannot be nil' + end + + pattern = Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + if name !~ pattern + fail ArgumentError, "invalid value for \"name\", must conform to the pattern #{pattern}." + end + + @name = name + end + + # Custom attribute writer method checking allowed values (enum). + # @param [Object] status Object to be assigned + def status=(status) + validator = EnumAttributeValidator.new('String', ["ready", "unavailable", "deleting"]) + unless validator.valid?(status) + fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}." + end + @status = status + end + + # Custom attribute writer method with validation + # @param [Object] created_at Value to be assigned + def created_at=(created_at) + if created_at.nil? + fail ArgumentError, 'created_at cannot be nil' + end + + @created_at = created_at + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + id == o.id && + project_id == o.project_id && + name == o.name && + preset == o.preset && + memory_mb == o.memory_mb && + status == o.status && + created_at == o.created_at + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [id, project_id, name, preset, memory_mb, status, created_at].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/sandbox_template_page.rb b/lib/volcano/generated/lib/volcano-generated/models/sandbox_template_page.rb new file mode 100644 index 00000000..ad227414 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/sandbox_template_page.rb @@ -0,0 +1,192 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class SandboxTemplatePage < ApiModelBase + attr_accessor :data + + attr_accessor :pagination + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'data' => :'data', + :'pagination' => :'pagination' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'data' => :'Array', + :'pagination' => :'SandboxPagination' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::SandboxTemplatePage` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::SandboxTemplatePage`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'data') + if (value = attributes[:'data']).is_a?(Array) + self.data = value + end + else + self.data = nil + end + + if attributes.key?(:'pagination') + self.pagination = attributes[:'pagination'] + else + self.pagination = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @data.nil? + invalid_properties.push('invalid value for "data", data cannot be nil.') + end + + if @pagination.nil? + invalid_properties.push('invalid value for "pagination", pagination cannot be nil.') + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @data.nil? + return false if @pagination.nil? + true + end + + # Custom attribute writer method with validation + # @param [Object] data Value to be assigned + def data=(data) + if data.nil? + fail ArgumentError, 'data cannot be nil' + end + + @data = data + end + + # Custom attribute writer method with validation + # @param [Object] pagination Value to be assigned + def pagination=(pagination) + if pagination.nil? + fail ArgumentError, 'pagination cannot be nil' + end + + @pagination = pagination + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + data == o.data && + pagination == o.pagination + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [data, pagination].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/update_sandbox_template_request.rb b/lib/volcano/generated/lib/volcano-generated/models/update_sandbox_template_request.rb new file mode 100644 index 00000000..251eea39 --- /dev/null +++ b/lib/volcano/generated/lib/volcano-generated/models/update_sandbox_template_request.rb @@ -0,0 +1,175 @@ +=begin +#Volcano Hosting API + +#Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000). This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations. + +The version of the OpenAPI document: 3.0.0 +Contact: support@volcano.dev +Generated by: https://openapi-generator.tech +Generator version: 7.17.0 + +=end + +require 'date' +require 'time' + +module Volcano::Generated + class UpdateSandboxTemplateRequest < ApiModelBase + attr_accessor :name + + # Attribute mapping from ruby-style variable name to JSON key. + def self.attribute_map + { + :'name' => :'name' + } + end + + # Returns attribute mapping this model knows about + def self.acceptable_attribute_map + attribute_map + end + + # Returns all the JSON keys this model knows about + def self.acceptable_attributes + acceptable_attribute_map.values + end + + # Attribute type mapping. + def self.openapi_types + { + :'name' => :'String' + } + end + + # List of attributes with nullable: true + def self.openapi_nullable + Set.new([ + ]) + end + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(attributes = {}) + if (!attributes.is_a?(Hash)) + fail ArgumentError, "The input argument (attributes) must be a hash in `Volcano::Generated::UpdateSandboxTemplateRequest` initialize method" + end + + # check to see if the attribute exists and convert string to symbol for hash key + acceptable_attribute_map = self.class.acceptable_attribute_map + attributes = attributes.each_with_object({}) { |(k, v), h| + if (!acceptable_attribute_map.key?(k.to_sym)) + fail ArgumentError, "`#{k}` is not a valid attribute in `Volcano::Generated::UpdateSandboxTemplateRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect + end + h[k.to_sym] = v + } + + if attributes.key?(:'name') + self.name = attributes[:'name'] + else + self.name = nil + end + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + warn '[DEPRECATED] the `list_invalid_properties` method is obsolete' + invalid_properties = Array.new + if @name.nil? + invalid_properties.push('invalid value for "name", name cannot be nil.') + end + + pattern = Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + if @name !~ pattern + invalid_properties.push("invalid value for \"name\", must conform to the pattern #{pattern}.") + end + + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + warn '[DEPRECATED] the `valid?` method is obsolete' + return false if @name.nil? + return false if @name !~ Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + true + end + + # Custom attribute writer method with validation + # @param [Object] name Value to be assigned + def name=(name) + if name.nil? + fail ArgumentError, 'name cannot be nil' + end + + pattern = Regexp.new(/^[a-z][a-z0-9-]{0,62}$/) + if name !~ pattern + fail ArgumentError, "invalid value for \"name\", must conform to the pattern #{pattern}." + end + + @name = name + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.equal?(o) + self.class == o.class && + name == o.name + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [name].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + attributes = attributes.transform_keys(&:to_sym) + transformed_hash = {} + openapi_types.each_pair do |key, type| + if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = nil + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[attribute_map[key]].is_a?(Array) + transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) } + end + elsif !attributes[attribute_map[key]].nil? + transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]]) + end + end + new(transformed_hash) + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.include?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + end + +end diff --git a/lib/volcano/generated/lib/volcano-generated/models/variable.rb b/lib/volcano/generated/lib/volcano-generated/models/variable.rb index 15eaa70f..95e83126 100644 --- a/lib/volcano/generated/lib/volcano-generated/models/variable.rb +++ b/lib/volcano/generated/lib/volcano-generated/models/variable.rb @@ -18,6 +18,9 @@ class Variable < ApiModelBase # Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable. attr_accessor :shared + # Whether this name is in the project's shared frontend-variable list. + attr_accessor :frontend_shared + attr_accessor :id attr_accessor :project_id @@ -68,6 +71,7 @@ def valid?(value) def self.attribute_map { :'shared' => :'shared', + :'frontend_shared' => :'frontend_shared', :'id' => :'id', :'project_id' => :'project_id', :'name' => :'name', @@ -95,6 +99,7 @@ def self.acceptable_attributes def self.openapi_types { :'shared' => :'Boolean', + :'frontend_shared' => :'Boolean', :'id' => :'String', :'project_id' => :'String', :'name' => :'String', @@ -134,6 +139,10 @@ def initialize(attributes = {}) self.shared = attributes[:'shared'] end + if attributes.key?(:'frontend_shared') + self.frontend_shared = attributes[:'frontend_shared'] + end + if attributes.key?(:'id') self.id = attributes[:'id'] else @@ -331,6 +340,7 @@ def ==(o) return true if self.equal?(o) self.class == o.class && shared == o.shared && + frontend_shared == o.frontend_shared && id == o.id && project_id == o.project_id && name == o.name && @@ -352,7 +362,7 @@ def eql?(o) # Calculates hash code according to all attributes. # @return [Integer] Hash code def hash - [shared, id, project_id, name, value, status, current_sync_id, provisioning_started_at, deploy_source, created_at, updated_at].hash + [shared, frontend_shared, id, project_id, name, value, status, current_sync_id, provisioning_started_at, deploy_source, created_at, updated_at].hash end # Builds the object from hash diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 7393f3e4..4456681a 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -15,6 +15,8 @@ servers: - url: http://localhost:8000 description: Development API server (use VOLCANO_API_URL env var) tags: + - name: Sandboxes + description: Isolated Linux sessions and reusable templates. - name: Projects description: Project management operations - name: Logs @@ -36,7 +38,7 @@ tags: - name: Variables description: Environment variable management - name: Databases - description: Serverless PostgreSQL database provisioning and management + description: PostgreSQL database provisioning and management - name: Database Branches description: Short-lived forks of a database for development and testing - name: Database Queries @@ -51,6 +53,8 @@ tags: description: Project-specific public keys for frontend auth - name: Service Keys description: Project-specific secret keys for admin operations (bypass RLS - backend only!) + - name: Project Access Tokens + description: Project-scoped credentials for calling the Volcano API from CI, scripts, and agents - name: OAuth Configuration description: OAuth provider configuration (Google, GitHub, Microsoft, Apple) - name: OAuth Authentication @@ -80,520 +84,725 @@ tags: and polls for completion. Session completion is handled by volcano.dev via the Management API. paths: - /user/imports/connect: - post: + /sandboxes/presets: + get: tags: - - Project Imports - summary: Start a project import provider connection - description: | - Starts a first-party dashboard user's provider connection flow. The - response sets a short-lived HttpOnly browser-binding cookie for the - public provider callback. - operationId: startImportConnect - security: - - UserToken: [] - - AuthUserAccessToken: [] - parameters: - - name: provider - in: query - required: false - description: Import provider to connect. Defaults to Vercel. - schema: - $ref: '#/components/schemas/ImportProvider' - - name: redirect - in: query - required: false - description: Validated application URL used after the provider callback. - schema: - type: string - format: uri - pattern: ^https://[^/?#]+(?:[/?][^#]*)?$|^http://(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?(?:[/?][^#]*)?$ + - Sandboxes + summary: List available sandbox presets + operationId: listSandboxPresets + security: [] responses: '200': - description: Provider authorization URL - content: - application/json: - schema: - $ref: '#/components/schemas/ImportConnectStartResponse' - '400': - description: Unsupported provider or invalid redirect + description: List available sandbox presets content: application/json: schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + $ref: '#/components/schemas/SandboxPresetList' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to start the connection + /projects/{id}/sandboxes: + get: + tags: + - Sandboxes + summary: List sandbox templates + operationId: listSandboxes + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: id + in: path + required: true + schema: + type: string + format: uuid + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + responses: + '200': + description: List sandbox templates content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': - description: Import provider integration is not configured + $ref: '#/components/schemas/SandboxTemplatePage' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - /imports/{provider}/callback: - get: + post: tags: - - Project Imports - summary: Complete a project import provider connection - description: | - Public provider callback protected by signed state and the browser-binding - cookie created by startImportConnect. - operationId: completeImportConnect - security: [] + - Sandboxes + summary: Create a sandbox template from a verified preset + operationId: createSandbox + security: + - UserToken: [] + - ServiceRoleKey: [] parameters: - - name: provider + - name: id in: path required: true - schema: - $ref: '#/components/schemas/ImportProvider' - - name: state - in: query - required: true - description: Signed connect state generated by startImportConnect. - schema: - type: string - - name: code - in: query - required: false - description: Provider authorization code. - schema: - type: string - - name: error - in: query - required: false - description: Provider error category. - schema: - type: string - - name: teamId - in: query - required: false - description: Vercel team selected during installation. - schema: - type: string - - name: configurationId - in: query - required: false - description: Vercel Integration configuration identifier. - schema: - type: string - - name: next - in: query - required: false - description: Provider completion URL validated by the provider adapter. schema: type: string - - name: source - in: query - required: false - description: Vercel installation source indicator. + format: uuid + - name: Idempotency-Key + in: header + required: true schema: type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateSandboxTemplateRequest' responses: - '303': - description: Redirect to the provider completion URL, signed application redirect, or Volcano import page - headers: - Location: - description: Validated redirect target - schema: - type: string - '400': - description: Invalid callback request, state, or browser binding - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '429': - description: Too many callback attempts - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Failed to complete the connection + '201': + description: Create a sandbox template from a verified preset content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': - description: Import provider integration is not configured + $ref: '#/components/schemas/SandboxTemplate' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - /user/imports/connections: + /projects/{id}/sandboxes/{sandboxId}: get: tags: - - Project Imports - summary: List project import provider connections - operationId: listImportConnections + - Sandboxes + summary: Get a sandbox template + operationId: getSandbox security: - UserToken: [] - - AuthUserAccessToken: [] + - ServiceRoleKey: [] + parameters: + - name: id + in: path + required: true + schema: + type: string + format: uuid + - name: sandboxId + in: path + required: true + schema: + type: string + format: uuid responses: '200': - description: Stored import provider connections - content: - application/json: - schema: - $ref: '#/components/schemas/ImportConnectionsResponse' - '401': - description: Not authenticated + description: Get a sandbox template content: application/json: schema: - $ref: '#/components/schemas/Error' - '500': - description: Failed to list connections + $ref: '#/components/schemas/SandboxTemplate' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - /user/imports/connections/{connectionId}: - delete: + patch: tags: - - Project Imports - summary: Delete a project import provider connection - operationId: deleteImportConnection + - Sandboxes + summary: Rename a sandbox template + operationId: updateSandbox security: - UserToken: [] - - AuthUserAccessToken: [] + - ServiceRoleKey: [] parameters: - - name: connectionId + - name: id + in: path + required: true + schema: + type: string + format: uuid + - name: sandboxId in: path required: true - description: Connection ID to delete. schema: type: string format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateSandboxTemplateRequest' responses: - '204': - description: Connection deleted - '400': - description: Malformed connection ID - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Connection not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: Connection changed while it was being deleted - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Failed to delete the connection + '200': + description: Rename a sandbox template content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': - description: Import provider integration is not configured + $ref: '#/components/schemas/SandboxTemplate' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - /imports/{provider}/sources: - get: + delete: tags: - - Project Imports - summary: List project sources available from a provider connection - description: Lists provider projects without changing provider or Volcano resources. - operationId: listImportSources + - Sandboxes + summary: Retire a template and terminate its sessions + operationId: deleteSandbox security: - UserToken: [] - - AuthUserAccessToken: [] + - ServiceRoleKey: [] parameters: - - name: provider + - name: id in: path required: true schema: - $ref: '#/components/schemas/ImportProvider' - - name: connection_id - in: query + type: string + format: uuid + - name: sandboxId + in: path required: true - description: Owned provider connection used for discovery. schema: type: string format: uuid responses: - '200': - description: Provider sources available to import - content: - application/json: - schema: - $ref: '#/components/schemas/ImportSourcesResponse' - '400': - description: Invalid provider or connection ID - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '202': + description: Retire a template and terminate its sessions + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: The provider connection lacks a required Integration scope + /projects/{id}/sandboxes/{sandboxId}/deployments: + get: + tags: + - Sandboxes + summary: List sandbox deployment history + operationId: listSandboxDeployments + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: id + in: path + required: true + schema: + type: string + format: uuid + - name: sandboxId + in: path + required: true + schema: + type: string + format: uuid + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + responses: + '200': + description: List sandbox deployment history content: application/json: schema: - $ref: '#/components/schemas/Error' - '404': - description: Connection or provider source not found + $ref: '#/components/schemas/SandboxDeploymentPage' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: The provider connection must be reconnected + /projects/{id}/sandbox-sessions: + get: + tags: + - Sandboxes + summary: List project sandbox sessions + operationId: listSandboxSessions + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: id + in: path + required: true + schema: + type: string + format: uuid + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + responses: + '200': + description: List project sandbox sessions content: application/json: schema: - $ref: '#/components/schemas/Error' - '429': - description: Provider rate limit exceeded + $ref: '#/components/schemas/SandboxSessionPage' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to list provider sources + post: + tags: + - Sandboxes + summary: Start a sandbox session + operationId: createSandboxSession + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: id + in: path + required: true + schema: + type: string + format: uuid + - name: Idempotency-Key + in: header + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateSandboxSessionRequest' + responses: + '201': + description: Start a sandbox session content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': - description: Provider unavailable or integration not configured + $ref: '#/components/schemas/SandboxSession' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - /imports/{provider}/preflight: + /projects/{id}/sandbox-executions: post: tags: - - Project Imports - summary: Check whether a provider project is ready to import - description: Produces a deterministic read-only readiness report for a proposed new Volcano project. - operationId: preflightProjectImport + - Sandboxes + summary: Execute once and return after confirmed termination + operationId: executeSandbox security: - UserToken: [] - - AuthUserAccessToken: [] + - ServiceRoleKey: [] parameters: - - name: provider + - name: id in: path required: true schema: - $ref: '#/components/schemas/ImportProvider' + type: string + format: uuid + - name: Idempotency-Key + in: header + required: true + schema: + type: string + format: uuid requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/ProjectImportPreflightRequest' + $ref: '#/components/schemas/SandboxExecutionRequest' responses: '200': - description: Import readiness report + description: Execute once and return after confirmed termination content: application/json: schema: - $ref: '#/components/schemas/ProjectImportReport' - '400': - description: Invalid provider, source, project name, or target + $ref: '#/components/schemas/SandboxExecutionResult' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + /sandbox-sessions/{sessionId}: + get: + tags: + - Sandboxes + summary: Get a sandbox session + operationId: getSandboxSession + security: + - UserToken: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Get a sandbox session content: application/json: schema: - $ref: '#/components/schemas/Error' - '403': - description: The provider connection lacks a required Integration scope + $ref: '#/components/schemas/SandboxSession' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Connection or provider source not found + delete: + tags: + - Sandboxes + summary: Request sandbox termination + operationId: terminateSandboxSession + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + responses: + '202': + description: Request sandbox termination content: application/json: schema: - $ref: '#/components/schemas/Error' - '409': - description: The provider connection must be reconnected + $ref: '#/components/schemas/SandboxSession' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - description: Provider rate limit exceeded + /sandbox-sessions/{sessionId}/suspend: + post: + tags: + - Sandboxes + summary: Suspend a sandbox session + operationId: suspendSandboxSession + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + responses: + '202': + description: Suspend a sandbox session content: application/json: schema: - $ref: '#/components/schemas/Error' - '500': - description: Failed to produce an import readiness report + $ref: '#/components/schemas/SandboxSession' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Provider unavailable or integration not configured + /sandbox-sessions/{sessionId}/resume: + post: + tags: + - Sandboxes + summary: Resume a sandbox session + operationId: resumeSandboxSession + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + responses: + '202': + description: Resume a sandbox session + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxSession' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - /imports/{provider}/runs: + /sandbox-sessions/{sessionId}/exec: post: tags: - - Project Imports - summary: Start a Vercel project import - description: Creates a Volcano project from an importable production preflight report. Retrying the same request with the same Idempotency-Key returns the existing run. - operationId: startProjectImport + - Sandboxes + summary: Execute a command within a session + operationId: executeSandboxSession security: - UserToken: [] + - ServiceRoleKey: [] - AuthUserAccessToken: [] parameters: - - name: provider + - name: sessionId in: path required: true schema: - $ref: '#/components/schemas/ImportProvider' + type: string + format: uuid - name: Idempotency-Key in: header required: true schema: type: string - minLength: 1 - maxLength: 255 - pattern: ^[!-~]+$ + format: uuid requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/ProjectImportStartRequest' + $ref: '#/components/schemas/SandboxCommandRequest' responses: - '202': - description: Import run accepted - headers: - Location: - required: true - schema: - type: string - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectImportRun' - '400': - description: Invalid request or idempotency key - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '200': + description: Execute a command within a session content: application/json: schema: - $ref: '#/components/schemas/Error' - '403': - description: Provider permission or project admission denied + $ref: '#/components/schemas/SandboxCommandResult' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Connection or provider source not found + /sandbox-sessions/{sessionId}/files/read: + post: + tags: + - Sandboxes + summary: Read a workspace file + operationId: readSandboxSessionFile + security: + - UserToken: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxFileReadRequest' + responses: + '200': + description: Read a workspace file content: application/json: schema: - $ref: '#/components/schemas/Error' - '409': - description: Preflight is stale, idempotency key was reused, or destination conflicts + $ref: '#/components/schemas/SandboxFileResult' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '422': - description: Source is not importable + /sandbox-sessions/{sessionId}/files/write: + post: + tags: + - Sandboxes + summary: Write a workspace file + operationId: writeSandboxSessionFile + security: + - UserToken: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxFileWriteRequest' + responses: + '204': + description: Write a workspace file + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - description: Provider rate limit exceeded + /sandbox-sessions/{sessionId}/grants/{subjectId}: + put: + tags: + - Sandboxes + summary: Authorize an authenticated project user for this session + operationId: grantSandboxSession + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + - name: subjectId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxSubjectGrantRequest' + responses: + '204': + description: Authorize an authenticated project user for this session + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to start the import + delete: + tags: + - Sandboxes + summary: Revoke a project user session grant + operationId: revokeSandboxSession + security: + - UserToken: [] + - ServiceRoleKey: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + - name: subjectId + in: path + required: true + schema: + type: string + format: uuid + responses: + '204': + description: Revoke a project user session grant + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Provider unavailable or integration not configured + /sandbox-sessions/{sessionId}/access: + post: + tags: + - Sandboxes + summary: Issue a short-lived port-scoped access credential + operationId: createSandboxSessionAccess + security: + - UserToken: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxAccessRequest' + responses: + '200': + description: Issue a short-lived port-scoped access credential + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxAccess' + default: + description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503). content: application/json: schema: $ref: '#/components/schemas/Error' - /imports/{provider}/runs/{runId}: - get: + /user/imports/connect: + post: tags: - Project Imports - summary: Get a project import run - operationId: getProjectImportRun + summary: Start a project import provider connection + description: | + Starts a first-party dashboard user's provider connection flow. The + response sets a short-lived HttpOnly browser-binding cookie for the + public provider callback. + operationId: startImportConnect security: - UserToken: [] - AuthUserAccessToken: [] parameters: - name: provider - in: path - required: true + in: query + required: false + description: Import provider to connect. Defaults to Vercel. schema: $ref: '#/components/schemas/ImportProvider' - - name: runId - in: path - required: true + - name: redirect + in: query + required: false + description: Validated application URL used after the provider callback. schema: type: string - format: uuid + format: uri + pattern: ^https://[^/?#]+(?:[/?][^#]*)?$|^http://(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?(?:[/?][^#]*)?$ + - name: callback_url + in: query + required: false + description: Same-origin browser callback used to relay provider parameters before completing the connection. + schema: + type: string + format: uri + pattern: ^https://[^/?#]+/[^?#]*$|^http://(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?/[^?#]*$ responses: '200': - description: Import run status + description: Provider authorization URL content: application/json: schema: - $ref: '#/components/schemas/ProjectImportRun' + $ref: '#/components/schemas/ImportConnectStartResponse' '400': - description: Invalid import run ID + description: Unsupported provider or invalid redirect content: application/json: schema: @@ -604,95 +813,124 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Import run not found + '500': + description: Failed to start the connection content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to get the import run + '503': + description: Import provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /user/git/connect: - post: + /imports/{provider}/callback: + get: tags: - - Git Connections - summary: Start a git provider connection + - Project Imports + summary: Complete a project import provider connection description: | - Starts a first-party dashboard user's git provider connection flow and - returns the provider authorization URL. The response also sets a - short-lived HttpOnly callback binding cookie tied to the authenticated - user through the signed provider state. - operationId: startGitConnect - security: - - UserToken: [] - - AuthUserAccessToken: [] + Public provider callback protected by signed state and the browser-binding + cookie created by startImportConnect. + operationId: completeImportConnect + security: [] parameters: - name: provider + in: path + required: true + schema: + $ref: '#/components/schemas/ImportProvider' + - name: state + in: query + required: true + description: Signed connect state generated by startImportConnect. + schema: + type: string + - name: code in: query required: false - description: Git provider to connect. Defaults to github. + description: Provider authorization code. schema: type: string - enum: - - github - default: github - - name: redirect + - name: error in: query required: false - description: URL to redirect the browser to after the provider callback completes. + description: Provider error category. + schema: + type: string + - name: teamId + in: query + required: false + description: Vercel team selected during installation. + schema: + type: string + - name: configurationId + in: query + required: false + description: Vercel Integration configuration identifier. + schema: + type: string + - name: next + in: query + required: false + description: Provider completion URL validated by the provider adapter. + schema: + type: string + - name: source + in: query + required: false + description: Vercel installation source indicator. schema: type: string responses: - '200': - description: Provider authorization URL - content: - application/json: + '303': + description: Redirect to the provider completion URL, signed application redirect, or Volcano import page + headers: + Location: + description: Validated redirect target schema: - $ref: '#/components/schemas/GitConnectStartResponse' + type: string '400': - description: Unsupported provider or invalid redirect + description: Invalid callback request, state, or browser binding content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '429': + description: Too many callback attempts content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Failed to start the connection + description: Failed to complete the connection content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Git provider integration is not configured + description: Import provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /user/git/connections: + /user/imports/connections: get: tags: - - Git Connections - summary: List git provider connections - operationId: listGitConnections + - Project Imports + summary: List project import provider connections + operationId: listImportConnections security: - UserToken: [] - AuthUserAccessToken: [] responses: '200': - description: Stored git provider connections + description: Stored import provider connections content: application/json: schema: - $ref: '#/components/schemas/GitConnectionsResponse' + $ref: '#/components/schemas/ImportConnectionsResponse' '401': description: Not authenticated content: @@ -705,18 +943,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Git provider integration is not configured - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /user/git/connections/{connectionId}: + /user/imports/connections/{connectionId}: delete: tags: - - Git Connections - summary: Delete a git provider connection - operationId: deleteGitConnection + - Project Imports + summary: Delete a project import provider connection + operationId: deleteImportConnection security: - UserToken: [] - AuthUserAccessToken: [] @@ -724,7 +956,7 @@ paths: - name: connectionId in: path required: true - description: Connection ID to delete + description: Connection ID to delete. schema: type: string format: uuid @@ -749,48 +981,56 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + '409': + description: Connection changed while it was being deleted + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '500': - description: Failed to delete connection + description: Failed to delete the connection content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Git provider integration is not configured + description: Import provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /user/git/connections/{connectionId}/installations: + /imports/{provider}/sources: get: tags: - - Git Connections - summary: List GitHub App installations accessible to a connection - description: | - Live proxy to GitHub: lists the platform GitHub App installations the - connection's stored user token can access. Nothing is persisted by - this call. - operationId: listGitInstallations + - Project Imports + summary: List project sources available from a provider connection + description: Lists provider projects without changing provider or Volcano resources. + operationId: listImportSources security: - UserToken: [] - AuthUserAccessToken: [] parameters: - - name: connectionId + - name: provider in: path required: true - description: Connection ID to browse installations for. + schema: + $ref: '#/components/schemas/ImportProvider' + - name: connection_id + in: query + required: true + description: Owned provider connection used for discovery. schema: type: string format: uuid responses: '200': - description: Installations accessible to the connection + description: Provider sources available to import content: application/json: schema: - $ref: '#/components/schemas/GitInstallationsResponse' + $ref: '#/components/schemas/ImportSourcesResponse' '400': - description: Malformed connection ID + description: Invalid provider or connection ID content: application/json: schema: @@ -801,61 +1041,73 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + '403': + description: The provider connection lacks a required Integration scope + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Connection not found + description: Connection or provider source not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: The provider connection must be reconnected + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Provider rate limit exceeded content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Failed to list installations + description: Failed to list provider sources content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Git provider integration is not configured + description: Provider unavailable or integration not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /user/git/connections/{connectionId}/installations/{installationId}/repositories: - get: + /imports/{provider}/preflight: + post: tags: - - Git Connections - summary: List repos accessible to a connection through an installation - description: | - Live proxy to GitHub: lists the repos the connection's stored user - token can access through installationId. Nothing is persisted by this - call. - operationId: listGitInstallationRepositories + - Project Imports + summary: Check whether a provider project is ready to import + description: Produces a deterministic read-only readiness report for a proposed new Volcano project. + operationId: preflightProjectImport security: - UserToken: [] - AuthUserAccessToken: [] parameters: - - name: connectionId - in: path - required: true - description: Connection ID to browse repositories for. - schema: - type: string - format: uuid - - name: installationId + - name: provider in: path required: true - description: GitHub App installation ID. schema: - type: integer - format: int64 + $ref: '#/components/schemas/ImportProvider' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectImportPreflightRequest' responses: '200': - description: Repositories accessible through the installation + description: Import readiness report content: application/json: schema: - $ref: '#/components/schemas/GitRepositoriesResponse' + $ref: '#/components/schemas/ProjectImportReport' '400': - description: Malformed connection or installation ID + description: Invalid provider, source, project name, or target content: application/json: schema: @@ -866,762 +1118,673 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + '403': + description: The provider connection lacks a required Integration scope + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Connection not found + description: Connection or provider source not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: The provider connection must be reconnected + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Provider rate limit exceeded content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Failed to list repositories + description: Failed to produce an import readiness report content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Git provider integration is not configured + description: Provider unavailable or integration not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /github/callback: - get: + /imports/{provider}/runs: + post: tags: - - Git Connections - summary: Complete a GitHub App connection callback - description: | - Public GitHub App callback. The signed state and callback binding cookie - bind the provider authorization to the browser that started the flow. - operationId: gitConnectCallback - security: [] + - Project Imports + summary: Start a Vercel project import + description: Creates a Volcano project from an importable production preflight report. Retrying the same request with the same Idempotency-Key returns the existing run. + operationId: startProjectImport + security: + - UserToken: [] + - AuthUserAccessToken: [] parameters: - - name: code - in: query - required: false - description: GitHub user authorization code. - schema: - type: string - - name: state - in: query + - name: provider + in: path required: true - description: Signed connect state generated by startGitConnect. schema: - type: string - - name: error - in: query - required: false - description: Provider error returned by GitHub. + $ref: '#/components/schemas/ImportProvider' + - name: Idempotency-Key + in: header + required: true schema: type: string + minLength: 1 + maxLength: 255 + pattern: ^[!-~]+$ + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectImportStartRequest' responses: - '303': - description: Redirect back to the app after a successful or failed connect attempt + '202': + description: Import run accepted headers: Location: - description: Redirect target + required: true schema: type: string + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectImportRun' '400': - description: Invalid callback request or state + description: Invalid request or idempotency key + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Provider permission or project admission denied + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Connection or provider source not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: Preflight is stale, idempotency key was reused, or destination conflicts + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '422': + description: Source is not importable content: application/json: schema: $ref: '#/components/schemas/Error' '429': - description: Too many callback attempts from this client + description: Provider rate limit exceeded content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Failed to complete the connection + description: Failed to start the import content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Git provider integration is not configured + description: Provider unavailable or integration not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /projects: + /imports/{provider}/runs/{runId}: get: tags: - - Projects - summary: List all projects for authenticated user - description: | - Returns projects that are not deleting or deleted, newest first. - Supports two mutually exclusive pagination modes. Offset mode uses - `page` and `limit`. Cursor mode uses `cursor` or `ending_before` with - `limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded - `offset` past the cursor anchor. Supplying `limit` without `page` - selects cursor mode. `search` applies a case-insensitive project-name - filter in either mode. `include` optionally expands each returned - project with its Git connection and/or aggregate health summary using - `git_connection` and `health`. Sending `page` with `cursor` or `ending_before`, - or sending both cursor directions, returns 400. - operationId: listProjects + - Project Imports + summary: Get a project import run + operationId: getProjectImportRun security: - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' - - name: include - in: query - required: false - description: Optional comma-separated project metadata expansions. - style: form - explode: false - schema: - type: array - uniqueItems: true - items: - type: string - enum: - - git_connection - - health + - name: provider + in: path + required: true + schema: + $ref: '#/components/schemas/ImportProvider' + - name: runId + in: path + required: true + schema: + type: string + format: uuid responses: '200': - description: Successful response + description: Import run status content: application/json: schema: - $ref: '#/components/schemas/PaginatedProjects' + $ref: '#/components/schemas/ProjectImportRun' '400': - description: Invalid or conflicting pagination parameters + description: Invalid import run ID content: application/json: schema: $ref: '#/components/schemas/Error' - post: - tags: - - Projects - summary: Create a new project - description: | - Creates a project for the authenticated user. - Each user can create up to 1,000 projects. Requests over this cap return 403. - operationId: createProject - security: - - UserToken: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateProjectRequest' - responses: - '201': - description: Project created - content: - application/json: - schema: - $ref: '#/components/schemas/Project' - '400': - description: Bad request + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Project limit exceeded for the user + '404': + description: Import run not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}: - get: - tags: - - Projects - summary: Get project by ID - operationId: getProject - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/Project' - '404': - description: Project not found + '500': + description: Failed to get the import run content: application/json: schema: $ref: '#/components/schemas/Error' - patch: + /user/git/connect: + post: tags: - - Projects - summary: Update project metadata and region policy - operationId: updateProject + - Git Connections + summary: Start a git provider connection + description: | + Starts a first-party dashboard user's git provider connection flow and + returns the provider authorization URL. The response also sets a + short-lived HttpOnly callback binding cookie tied to the authenticated + user through the signed provider state. + operationId: startGitConnect security: - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateProjectRequest' + - name: provider + in: query + required: false + description: Git provider to connect. Defaults to github. + schema: + type: string + enum: + - github + default: github + - name: redirect + in: query + required: false + description: URL to redirect the browser to after the provider callback completes. + schema: + type: string + - name: callback_url + in: query + required: false + description: Same-origin browser callback used to relay provider parameters before completing the connection. + schema: + type: string + format: uri + pattern: ^https://[^/?#]+/[^?#]*$|^http://(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?/[^?#]*$ responses: '200': - description: Project updated + description: Provider authorization URL content: application/json: schema: - $ref: '#/components/schemas/Project' + $ref: '#/components/schemas/GitConnectStartResponse' '400': - description: | - Bad request (no region selected, an unknown region, or — for a - project holding durable functions — a region that does not offer - durable execution) - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden (for example, selecting subset regions on non-SUPERAGENT plan) + description: Unsupported provider or invalid redirect content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Project not found + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Conflict (project name already exists or a resource deployment blocks a region change) + '500': + description: Failed to start the connection content: application/json: schema: $ref: '#/components/schemas/Error' - delete: - tags: - - Projects - summary: Delete a project - description: | - Starts asynchronous project deletion. The project remains available from - `GET /projects/{id}` with `status: deleting` until cleanup finishes, but is - removed from project lists as soon as deletion starts. After cleanup it - returns 404. - operationId: deleteProject - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - responses: - '202': - description: Project deletion started - '404': - description: Project not found + '503': + description: Git provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/health: + /user/git/connections: get: tags: - - Projects - summary: Get project health - description: | - Returns a fast control-plane health snapshot for the project and its - deployed resources. The endpoint does not run live provider probes. - A successful request returns 200 even when the project status is - `unhealthy`; transport and authorization failures use HTTP errors. - operationId: getProjectHealth + - Git Connections + summary: List git provider connections + operationId: listGitConnections security: - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - AuthUserAccessToken: [] responses: '200': - description: Project health snapshot retrieved + description: Stored git provider connections content: application/json: schema: - $ref: '#/components/schemas/ProjectHealthResponse' + $ref: '#/components/schemas/GitConnectionsResponse' '401': - description: Unauthorized - invalid or missing token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Access denied + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Project not found + '500': + description: Failed to list connections content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal server error + '503': + description: Git provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/metrics/query: - post: + /user/git/connections/{connectionId}: + delete: tags: - - Projects - summary: Query project runtime metrics - description: | - Evaluates a batch of named, curated runtime metric queries over one - trailing time range. Query IDs correlate each request with its result; - raw backend query languages are intentionally not exposed. - operationId: queryProjectMetrics + - Git Connections + summary: Delete a git provider connection + operationId: deleteGitConnection security: - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectMetricsQueryRequest' + - name: connectionId + in: path + required: true + description: Connection ID to delete + schema: + type: string + format: uuid responses: - '200': - description: Project runtime metric queries evaluated - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectMetricsQueryResponse' + '204': + description: Connection deleted '400': - description: Invalid metric query + description: Malformed connection ID content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Unauthorized - invalid or missing token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Access denied + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project not found + description: Connection not found content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Internal server error + description: Failed to delete connection content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Runtime metrics backend unavailable + description: Git provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/logo: + /user/git/connections/{connectionId}/installations: get: tags: - - Projects - summary: Get the project logo image + - Git Connections + summary: List GitHub App installations accessible to a connection description: | - Returns the raw logo image stored in the project's storage folder. This - endpoint is unauthenticated so the asset can be rendered directly in an - `` tag; project IDs are unguessable UUIDs and logos are - non-sensitive branding. The `Project.logo_url` field exposes a versioned - path to this endpoint. - operationId: getProjectLogo - security: [] + Live proxy to GitHub: lists the platform GitHub App installations the + connection's stored user token can access. Nothing is persisted by + this call. + operationId: listGitInstallations + security: + - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' + - name: connectionId + in: path + required: true + description: Connection ID to browse installations for. + schema: + type: string + format: uuid responses: '200': - description: Logo image + description: Installations accessible to the connection content: - image/png: + application/json: schema: - type: string - format: binary - image/jpeg: + $ref: '#/components/schemas/GitInstallationsResponse' + '400': + description: Malformed connection ID + content: + application/json: schema: - type: string - format: binary - image/gif: + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated + content: + application/json: schema: - type: string - format: binary - image/webp: + $ref: '#/components/schemas/Error' + '404': + description: Connection not found + content: + application/json: schema: - type: string - format: binary - image/svg+xml: + $ref: '#/components/schemas/Error' + '500': + description: Failed to list installations + content: + application/json: schema: - type: string - format: binary - '404': - description: Project or logo not found + $ref: '#/components/schemas/Error' + '503': + description: Git provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - post: + /user/git/connections/{connectionId}/installations/{installationId}/repositories: + get: tags: - - Projects - summary: Upload or replace the project logo + - Git Connections + summary: List repos accessible to a connection through an installation description: | - Uploads an image as the project's logo, storing it in the project's - storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any - existing logo. Returns the updated project, whose `logo_url` reflects - the new logo. - operationId: uploadProjectLogo + Live proxy to GitHub: lists the repos the connection's stored user + token can access through installationId. Nothing is persisted by this + call. + operationId: listGitInstallationRepositories security: - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - required: - - logo - properties: - logo: - type: string - format: binary - description: Logo image (PNG, JPEG, GIF, WebP, or SVG; max 2 MB) + - name: connectionId + in: path + required: true + description: Connection ID to browse repositories for. + schema: + type: string + format: uuid + - name: installationId + in: path + required: true + description: GitHub App installation ID. + schema: + type: integer + format: int64 responses: '200': - description: Logo uploaded + description: Repositories accessible through the installation content: application/json: schema: - $ref: '#/components/schemas/Project' + $ref: '#/components/schemas/GitRepositoriesResponse' '400': - description: Bad request (missing file, unsupported type, or too large) + description: Malformed connection or installation ID content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project not found + description: Connection not found content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Project is being deleted + '500': + description: Failed to list repositories content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Logo storage is not configured + description: Git provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /github/callback: + get: tags: - - Projects - summary: Remove the project logo + - Git Connections + summary: Complete a GitHub App connection callback description: | - Deletes the project logo from the project's storage folder and clears its - record. Returns the updated project with no `logo_url`. - operationId: deleteProjectLogo - security: - - UserToken: [] + Public GitHub App callback. The signed state and callback binding cookie + bind the provider authorization to the browser that started the flow. + operationId: gitConnectCallback + security: [] parameters: - - $ref: '#/components/parameters/ProjectId' + - name: code + in: query + required: false + description: GitHub user authorization code. + schema: + type: string + - name: state + in: query + required: true + description: Signed connect state generated by startGitConnect. + schema: + type: string + - name: error + in: query + required: false + description: Provider error returned by GitHub. + schema: + type: string responses: - '200': - description: Logo removed - content: - application/json: + '303': + description: Redirect back to the app after a successful or failed connect attempt + headers: + Location: + description: Redirect target schema: - $ref: '#/components/schemas/Project' - '403': - description: Access denied + type: string + '400': + description: Invalid callback request or state content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Project not found + '429': + description: Too many callback attempts from this client content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Project is being deleted + '500': + description: Failed to complete the connection content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Logo storage is not configured + description: Git provider integration is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/usage: + /projects: get: tags: - Projects - summary: Get usage metrics for a project + summary: List all projects for authenticated user description: | - Returns project usage totals for the current usage month plus - recent hourly and daily time series for each tracked metric. - operationId: getProjectUsage + Returns projects that are not deleting or deleted, newest first. + Supports two mutually exclusive pagination modes. Offset mode uses + `page` and `limit`. Cursor mode uses `cursor` or `ending_before` with + `limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded + `offset` past the cursor anchor. Supplying `limit` without `page` + selects cursor mode. `search` applies a case-insensitive project-name + filter in either mode. `include` optionally expands each returned + project with its Git connection and/or aggregate health summary using + `git_connection` and `health`. Sending `page` with `cursor` or `ending_before`, + or sending both cursor directions, returns 400. + operationId: listProjects security: - UserToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + - name: include + in: query + required: false + description: Optional comma-separated project metadata expansions. + style: form + explode: false + schema: + type: array + uniqueItems: true + items: + type: string + enum: + - git_connection + - health responses: '200': - description: Usage metrics retrieved - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectUsageResponse' - '403': - description: Access denied + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' - '404': - description: Project not found + $ref: '#/components/schemas/PaginatedProjects' + '400': + description: Invalid or conflicting pagination parameters content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/shared-variables: - put: + post: tags: - Projects - summary: Replace shared variable names + summary: Create a new project description: | - Atomically replaces the complete shared function-variable list without - changing values. Names must already exist. Validates final affected - function environments before membership or propagation side effects. - An empty list clears membership. Omitted names remain stored as non-shared variables. - operationId: replaceSharedVariables + Creates a project for the authenticated user. + Each user can create up to 1,000 projects. Requests over this cap return 403. + operationId: createProject security: - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: application/json: schema: - type: object - additionalProperties: false - required: - - shared_variables - not: - required: - - expected_shared_variables - - expected_shared_variables_digest - properties: - shared_variables: - type: array - uniqueItems: true - items: - type: string - maxLength: 256 - pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ - expected_shared_variables: - type: array - uniqueItems: true - description: When present, replace only if the current complete shared list matches this list. - items: - type: string - maxLength: 256 - pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ - expected_shared_variables_digest: - type: string - minLength: 64 - maxLength: 64 - pattern: ^[a-f0-9]{64}$ - description: SHA-256 of the sorted unique current shared names joined by a newline. Use instead of expected_shared_variables for a compact conditional replacement. + $ref: '#/components/schemas/CreateProjectRequest' responses: - '204': - description: Shared list replaced and affected function synchronization started. - '400': - description: Invalid names or final function environment. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - '404': - description: Project not found - '409': - description: Shared list changed since it was read. + '201': + description: Project created content: application/json: schema: - $ref: '#/components/schemas/Error' - '413': - description: Request body exceeds 4,194,304 bytes + $ref: '#/components/schemas/Project' + '400': + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Persistence or synchronization failed - '503': - description: Shared variable membership writes are disabled during rollout + '403': + description: Project limit exceeded for the user content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/config: + /projects/{id}: get: tags: - Projects - summary: Export project configuration - description: | - Exports the project's current user-facing configuration as a - declarative manifest. Returns JSON by default. Request the canonical - volcano-config.yaml rendering with `Accept: application/yaml` or - `?format=yaml`; the YAML is returned verbatim as the raw response body - (`Content-Type: application/yaml`) and is meant to be saved as-is. - Variable values and write-only secrets (SMTP password, OAuth client secrets, TLS material) - are omitted from the export; shared_variables contains names only; the YAML rendering adds a header comment - describing how to set them via CLI environment interpolation. - operationId: getProjectConfig + summary: Get project by ID + operationId: getProject security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: format - in: query - required: false - description: Response format override. Takes precedence over the Accept header. - schema: - type: string - enum: - - json - - yaml responses: '200': - description: | - Current project configuration. JSON by default; when YAML is - requested the body is the canonical volcano-config.yaml document - served verbatim with `Content-Type: application/yaml`. - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectConfig' - application/yaml: - schema: - type: string - format: binary - description: | - Canonical volcano-config.yaml document returned verbatim, - ready to be saved as-is. The response body is limited to - 4,194,304 bytes, matching the configuration apply limit. - '401': - description: Unauthorized - invalid or missing token + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/Project' '404': description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - '413': - description: Canonical YAML export exceeds 4,194,304 bytes - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - put: + patch: tags: - Projects - summary: Apply project configuration - description: | - Validates and applies a declarative configuration manifest to the - project, reconciling each declared section and returning a per-resource - report. Omitted sections are untouched. Declared collection keys - (`variables`, `buckets[].policies`, `auth.providers.oauth`, - `auth.email.templates`, `functions[].schedulers`) are fully synced: - resources absent from the manifest are deleted. Functions, frontends, - databases, and buckets are never created or deleted; manifest entries - for resources that do not exist are skipped and reported in `skipped`, - and existing resources missing from a declared section are reported in - `missing`. Validation failures (including plan-gate violations) return - 422 and nothing is applied. Set `dry_run=true` to get the projected - report without applying changes. Applies are serialized per project; - a concurrent apply returns 409. - operationId: applyProjectConfig + summary: Update project metadata and region policy + operationId: updateProject security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: dry_run - in: query - required: false - description: Validate and report projected actions without applying changes. - schema: - type: boolean - default: false requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/ProjectConfig' + $ref: '#/components/schemas/UpdateProjectRequest' responses: '200': - description: | - Apply report. Individual entries may still carry `action: error` - for apply-phase failures (summary.errors > 0); already-applied - changes are not rolled back. + description: Project updated content: application/json: schema: - $ref: '#/components/schemas/ProjectConfigApplyResult' + $ref: '#/components/schemas/Project' '400': - description: Malformed request body + description: | + Bad request (no region selected, an unknown region, or — for a + project holding durable functions — a region that does not offer + durable execution) content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + '403': + description: Forbidden (for example, selecting subset regions on plan other than SUPERAGENT) content: application/json: schema: @@ -1633,58 +1796,58 @@ paths: schema: $ref: '#/components/schemas/Error' '409': - description: Another apply is in progress for this project + description: Conflict (project name already exists or a resource deployment blocks a region change) content: application/json: schema: $ref: '#/components/schemas/Error' - '422': - description: Manifest validation failed; nothing was applied - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectConfigValidationErrorResponse' - '503': - description: Shared variable membership writes are disabled during rollout + delete: + tags: + - Projects + summary: Delete a project + description: | + Starts asynchronous project deletion. The project remains available from + `GET /projects/{id}` with `status: deleting` until cleanup finishes, but is + removed from project lists as soon as deletion starts. After cleanup it + returns 404. + operationId: deleteProject + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + responses: + '202': + description: Project deletion started + '404': + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/source-export: + /projects/{id}/health: get: tags: - Projects - - Git Connections - summary: Report the project's source-of-truth state - operationId: getProjectSourceExport + summary: Get project health description: | - Volcano stores the source of the functions and frontend it runs for a - project. This reports whether that source has been written to the - connected repository, and whether the repository has taken over as the - project's source of truth. - - `mode` is `platform`, `git_exporting`, `git_pending`, or `git`. Export - enters `git_exporting` before reading stored source. GitHub's signed - push event confirms that the initial commit reached the production - branch. That push or a newer production push changes the mode to - `git_pending` when it starts a deployment. `exported_at` records that - transition. - - A successful Git run completes the transition when it matches the - recorded repository, production branch, and root directory and actually - dispatches every recorded resource. Ordinary production-branch pushes - deploy without changing a platform-managed project's source ownership. + Returns a fast control-plane health snapshot for the project and its + deployed resources. The endpoint does not run live provider probes. + A successful request returns 200 even when the project status is + `unhealthy`; transport and authorization failures use HTTP errors. + operationId: getProjectHealth security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' responses: '200': - description: The project's source-of-truth state + description: Project health snapshot retrieved content: application/json: schema: - $ref: '#/components/schemas/ProjectSourceExportState' + $ref: '#/components/schemas/ProjectHealthResponse' '401': description: Unauthorized - invalid or missing token content: @@ -1692,7 +1855,7 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Forbidden - project not owned by the caller + description: Access denied content: application/json: schema: @@ -1709,42 +1872,19 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '501': - description: Source export is not available in this deployment mode - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + /projects/{id}/metrics/query: post: tags: - Projects - - Git Connections - summary: Initialize an empty repository with a project's stored source - operationId: exportProjectSource + summary: Query project runtime metrics description: | - Creates the first commit in the connected repository and pushes it - directly to the configured production branch. The push enters the - ordinary Git auto-deploy flow. Direct source writes remain frozen until - that deployment succeeds and the repository becomes the source of truth. - - The caller confirms the production branch shown before export. Starting - export pins that branch: later GitHub default-branch changes do not - repoint the project. If the configured branch changed after the caller - read it, the request fails without exporting so the caller can show and - confirm the new value. - - The response lists what the export could not carry: resources with no - successful deployment to take source from (`skipped`), and things no - export can hand back (`omitted`) — migrations, which Volcano stores no - copy of, and credential-shaped files, which are left for their owner to - add. - - Requires a connected repository with no commits or branches, and runs - once. Volcano never creates the repository. If GitHub did not confirm - the push, retrying creates the same commit and adopts it when it already - reached the repository. + Evaluates a batch of named, curated runtime metric queries over one + trailing time range. Query IDs correlate each request with its result; + raw backend query languages are intentionally not exposed. + operationId: queryProjectMetrics security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' requestBody: @@ -1752,16 +1892,16 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ExportProjectSourceRequest' + $ref: '#/components/schemas/ProjectMetricsQueryRequest' responses: - '201': - description: The initial production-branch commit that was pushed + '200': + description: Project runtime metric queries evaluated content: application/json: schema: - $ref: '#/components/schemas/ProjectSourceExport' + $ref: '#/components/schemas/ProjectMetricsQueryResponse' '400': - description: Malformed request body + description: Invalid metric query content: application/json: schema: @@ -1773,38 +1913,13 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Forbidden - project not owned by the caller + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project not found, or it has no repository connected - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: | - The source has already been exported, the repository has already - taken over as the source of truth, the confirmed production branch - is stale, a function or frontend deployment is still in progress, - or the project has no stored source to export - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '422': - description: | - The repository refused the branch, or its contents cannot be laid - out as a repository — a stored file that only ever carries - credentials, or a layout Git auto-deploy would not read back - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '429': - description: GitHub rate limited the request + description: Project not found content: application/json: schema: @@ -1815,360 +1930,421 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '501': - description: Source export is not available in this deployment mode - content: - application/json: - schema: - $ref: '#/components/schemas/Error' '503': - description: GitHub integration is not configured + description: Runtime metrics backend unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /projects/{id}/logo: + get: tags: - Projects - - Git Connections - summary: Cancel an incomplete source export - operationId: cancelProjectSourceExport + summary: Get the project logo image description: | - Restores platform source writes while the project is in - `git_exporting` or `git_pending`. If Volcano reserved or deployed the - root commit, export remains consumed and cannot be run again. The - connected repository and any commit already pushed to it are unchanged. - security: - - UserToken: [] + Returns the raw logo image stored in the project's storage folder. This + endpoint is unauthenticated so the asset can be rendered directly in an + `` tag; project IDs are unguessable UUIDs and logos are + non-sensitive branding. The `Project.logo_url` field exposes a versioned + path to this endpoint. + operationId: getProjectLogo + security: [] parameters: - $ref: '#/components/parameters/ProjectId' responses: - '204': - description: The incomplete source transition was canceled - '401': - description: Unauthorized - invalid or missing token + '200': + description: Logo image content: - application/json: + image/png: schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project not owned by the caller - content: - application/json: + type: string + format: binary + image/jpeg: schema: - $ref: '#/components/schemas/Error' - '404': - description: Project not found - content: - application/json: + type: string + format: binary + image/gif: schema: - $ref: '#/components/schemas/Error' - '409': - description: No incomplete transition exists, or Git already took ownership - content: - application/json: + type: string + format: binary + image/webp: schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: + type: string + format: binary + image/svg+xml: schema: - $ref: '#/components/schemas/Error' - '501': - description: Source export is not available in this deployment mode + type: string + format: binary + '404': + description: Project or logo not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/git-connection/production-branch: - put: + post: tags: - Projects - - Git Connections - summary: Set the branch a project deploys from + summary: Upload or replace the project logo description: | - Changes only the production branch, leaving the repository binding - alone. PUT /projects/{id}/git-connection can also set it, but that is a - full rebind: it needs connection_id, installation_id and a repository - selector resent, and re-resolves the repository against GitHub for a - field that does not depend on it. - - The branch does not have to exist. It is validated as a Git branch name - and nothing more, so a project can be pointed at a branch that is about - to be pushed — the case a repository created empty depends on. - - Setting the branch here marks it as the project's own choice, so a later - default-branch rename on GitHub no longer moves it. Projects that never - set one keep following the repository's default branch. - operationId: setProjectGitProductionBranch + Uploads an image as the project's logo, storing it in the project's + storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any + existing logo. Returns the updated project, whose `logo_url` reflects + the new logo. + operationId: uploadProjectLogo security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: - application/json: + multipart/form-data: schema: - $ref: '#/components/schemas/SetProjectGitProductionBranchRequest' + type: object + required: + - logo + properties: + logo: + type: string + format: binary + description: Logo image (PNG, JPEG, GIF, WebP, or SVG; max 2 MB) responses: '200': - description: The project's repo connection, with the new branch + description: Logo uploaded content: application/json: schema: - $ref: '#/components/schemas/ProjectGitConnection' + $ref: '#/components/schemas/Project' '400': - description: | - Malformed request body, or a production_branch that is not a valid - Git branch name - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + description: Bad request (missing file, unsupported type, or too large) content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Project not owned by the caller + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: | - Project not found, or it has no repository connected. The branch is - part of the connection, so there is nothing to set it on until one - exists. + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' '409': - description: A Git source transition is pending + description: Project is being deleted content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to set the production branch + '503': + description: Logo storage is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/git-connection: - get: + delete: tags: - Projects - - Git Connections - summary: Get a project's repo connection - operationId: getProjectGitConnection + summary: Remove the project logo + description: | + Deletes the project logo from the project's storage folder and clears its + record. Returns the updated project with no `logo_url`. + operationId: deleteProjectLogo security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' responses: '200': - description: The project's current repo connection + description: Logo removed content: application/json: schema: - $ref: '#/components/schemas/ProjectGitConnection' - '401': - description: Unauthorized - invalid or missing token + $ref: '#/components/schemas/Project' + '403': + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Project not owned by the caller + '404': + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Project not found, or has no repo connection + '409': + description: Project is being deleted content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to get project git connection + '503': + description: Logo storage is not configured content: application/json: schema: $ref: '#/components/schemas/Error' - put: + /projects/{id}/usage: + get: tags: - Projects - - Git Connections - summary: Connect or update a project's repo connection + summary: Get usage metrics for a project description: | - Full replace, following Vercel's model: many projects may point at the - same repo, so this only binds the project — it never creates or - deletes git-provider state. Used for both the initial connect and - later edits (repo change, root directory, production branch). - Resolves the repository_id or repo_full_name selector against the repos - accessible through installation_id via connection_id's stored GitHub - user token, then persists repository metadata only from that validated - GitHub response. - operationId: connectProjectGit + Returns project usage totals for the current usage month plus + recent hourly and daily time series for each tracked metric. + operationId: getProjectUsage security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ConnectProjectGitRequest' responses: '200': - description: The project's repo connection - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectGitConnection' - '400': - description: | - Malformed request body, no repository selector, selectors that - identify different repositories, a production_branch that is not a - valid Git branch name, no production_branch on a repository with no - default branch to follow (name one to connect a repository that has - no commits yet), or a production_branch other than the new - repository's default in a request that also changes repository. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + description: Usage metrics retrieved content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ProjectUsageResponse' '403': - description: | - Project not owned by the caller, or the selected repository is not - accessible through installation_id + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project or connection not found + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: | - A Git source transition is pending or complete, so the recorded - repository and root cannot be changed + /projects/{id}/shared-variables: + put: + tags: + - Projects + summary: Replace shared variable names + description: | + Atomically replaces the complete shared function-variable list without + changing values. Names must already exist. Validates final affected + function environments before membership or propagation side effects. + An empty list clears membership. Omitted names remain stored as non-shared variables. + operationId: replaceSharedVariables + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: false + required: + - shared_variables + not: + required: + - expected_shared_variables + - expected_shared_variables_digest + properties: + shared_variables: + type: array + uniqueItems: true + items: + type: string + maxLength: 256 + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + expected_shared_variables: + type: array + uniqueItems: true + description: When present, replace only if the current complete shared list matches this list. + items: + type: string + maxLength: 256 + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + expected_shared_variables_digest: + type: string + minLength: 64 + maxLength: 64 + pattern: ^[a-f0-9]{64}$ + description: SHA-256 of the sorted unique current shared names joined by a newline. Use instead of expected_shared_variables for a compact conditional replacement. + responses: + '204': + description: Shared list replaced and affected function synchronization started. + '400': + description: Invalid names or final function environment. content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to connect project git + '401': + description: Unauthorized + '404': + description: Project not found + '409': + description: Shared list changed since it was read. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '413': + description: Request body exceeds 4,194,304 bytes content: application/json: schema: $ref: '#/components/schemas/Error' + '500': + description: Persistence or synchronization failed '503': - description: Git provider integration is not configured + description: Shared variable membership writes are disabled during rollout content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /projects/{id}/frontend-shared-variables: + put: tags: - Projects - - Git Connections - summary: Disconnect a project's repo connection - operationId: disconnectProjectGit + summary: Replace frontend shared variable names + description: | + Atomically replaces the complete shared frontend-variable list without + changing values. Names must already exist. Validates final affected + frontend environments before membership or propagation side effects. + An empty list clears membership. Omitted names remain stored outside the frontend shared list. + operationId: replaceFrontendSharedVariables security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: false + required: + - frontend_shared_variables + not: + required: + - expected_frontend_shared_variables + - expected_frontend_shared_variables_digest + properties: + frontend_shared_variables: + type: array + uniqueItems: true + items: + type: string + maxLength: 256 + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + expected_frontend_shared_variables: + type: array + uniqueItems: true + description: When present, replace only if the current complete frontend shared list matches this list. + items: + type: string + maxLength: 256 + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + expected_frontend_shared_variables_digest: + type: string + minLength: 64 + maxLength: 64 + pattern: ^[a-f0-9]{64}$ + description: SHA-256 of the sorted unique current shared names joined by a newline. Use instead of expected_frontend_shared_variables for a compact conditional replacement. responses: '204': - description: Connection removed - '401': - description: Unauthorized - invalid or missing token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Project not owned by the caller + description: Frontend shared list replaced and affected frontend synchronization started. + '400': + description: Invalid names or final frontend environment. content: application/json: schema: $ref: '#/components/schemas/Error' + '401': + description: Unauthorized '404': - description: Project not found, or has no repo connection - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + description: Project not found '409': - description: | - A Git source transition is pending or complete, so the recorded - repository cannot be disconnected + description: Frontend shared list changed since it was read. content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to disconnect project git + '413': + description: Request body exceeds 4,194,304 bytes content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/git-deploy-settings: + '500': + description: Persistence or synchronization failed + /projects/{id}/config: get: tags: - Projects - - Git Connections - summary: Get a project's Git auto-deploy settings - operationId: getProjectGitDeploySettings + summary: Export project configuration + description: | + Exports the project's current user-facing configuration as a + declarative manifest. Returns JSON by default. Request the canonical + volcano-config.yaml rendering with `Accept: application/yaml` or + `?format=yaml`; the YAML is returned verbatim as the raw response body + (`Content-Type: application/yaml`) and is meant to be saved as-is. + Variable values and write-only secrets (SMTP password, OAuth client secrets, TLS material) + are omitted from the export; shared_variables and frontend_shared_variables contain names only; the YAML rendering adds a header comment + describing how to set them via CLI environment interpolation. + operationId: getProjectConfig security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' + - name: format + in: query + required: false + description: Response format override. Takes precedence over the Accept header. + schema: + type: string + enum: + - json + - yaml responses: '200': - description: The project's current Git auto-deploy settings + description: | + Current project configuration. JSON by default; when YAML is + requested the body is the canonical volcano-config.yaml document + served verbatim with `Content-Type: application/yaml`. content: application/json: schema: - $ref: '#/components/schemas/ProjectGitDeploySettings' + $ref: '#/components/schemas/ProjectConfig' + application/yaml: + schema: + type: string + format: binary + description: | + Canonical volcano-config.yaml document returned verbatim, + ready to be saved as-is. The response body is limited to + 4,194,304 bytes, matching the configuration apply limit. '401': description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Project not owned by the caller - content: - application/json: - schema: - $ref: '#/components/schemas/Error' '404': description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to get project git deploy settings + '413': + description: Canonical YAML export exceeds 4,194,304 bytes content: application/json: schema: @@ -2176,40 +2352,52 @@ paths: put: tags: - Projects - - Git Connections - summary: Update a project's Git auto-deploy settings + summary: Apply project configuration description: | - Full replace of the project's Git auto-deploy settings: what a push to - the connected repo's production branch deploys. - - Connecting a repository sets auto_deploy_enabled and deploy_functions - to true for a project that has never called this endpoint, so a push - deploys without any further setup. Once these settings have been saved - here they are the project's own: connecting, rebinding, disconnecting - and reconnecting all leave them untouched, including when they were - saved before any repository was connected. Frontend settings are off - until set here; the frontend need not exist when they are saved, since - frontend_name is resolved at deploy time. - operationId: updateProjectGitDeploySettings + Validates and applies a declarative configuration manifest to the + project, reconciling each declared section and returning a per-resource + report. Omitted sections are untouched. Declared collection keys + (`variables`, `buckets[].policies`, `auth.providers.oauth`, + `auth.email.templates`, `functions[].schedulers`) are fully synced: + resources absent from the manifest are deleted. Functions, frontends, + databases, and buckets are never created or deleted; manifest entries + for resources that do not exist are skipped and reported in `skipped`, + and existing resources missing from a declared section are reported in + `missing`. Validation failures (including plan-gate violations) return + 422 and nothing is applied. Set `dry_run=true` to get the projected + report without applying changes. Applies are serialized per project; + a concurrent apply returns 409. + operationId: applyProjectConfig security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' + - name: dry_run + in: query + required: false + description: Validate and report projected actions without applying changes. + schema: + type: boolean + default: false requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/UpdateProjectGitDeploySettingsRequest' + $ref: '#/components/schemas/ProjectConfig' responses: '200': - description: The project's updated Git auto-deploy settings + description: | + Apply report. Individual entries may still carry `action: error` + for apply-phase failures (summary.errors > 0); already-applied + changes are not rolled back. content: application/json: schema: - $ref: '#/components/schemas/ProjectGitDeploySettings' + $ref: '#/components/schemas/ProjectConfigApplyResult' '400': - description: Malformed request body, or frontend_app_root without frontend_name + description: Malformed request body content: application/json: schema: @@ -2220,12 +2408,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Project not owned by the caller - content: - application/json: - schema: - $ref: '#/components/schemas/Error' '404': description: Project not found content: @@ -2233,57 +2415,59 @@ paths: schema: $ref: '#/components/schemas/Error' '409': - description: | - A Git source transition is pending, or this change would remove - deploy coverage after Git has taken over + description: Another apply is in progress for this project content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to update project git deploy settings + '422': + description: Manifest validation failed; nothing was applied + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectConfigValidationErrorResponse' + '503': + description: Shared variable membership writes are disabled during rollout content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/queries: + /projects/{id}/source-export: get: tags: - - Databases - summary: Get database queries + - Projects + - Git Connections + summary: Report the project's source-of-truth state + operationId: getProjectSourceExport description: | - Returns the database's current top queries from pg_stat_statements - ranked by total execution time. + Volcano stores the source of the functions and frontend it runs for a + project. This reports whether that source has been written to the + connected repository, and whether the repository has taken over as the + project's source of truth. - **SUPERAGENT plan required.** This endpoint is only available to projects owned - by users on the SUPERAGENT billing plan. - operationId: getProjectDatabaseQueries + `mode` is `platform`, `git_exporting`, `git_pending`, or `git`. Export + enters `git_exporting` before reading stored source. GitHub's signed + push event confirms that the initial commit reached the production + branch. That push or a newer production push changes the mode to + `git_pending` when it starts a deployment. `exported_at` records that + transition. + + A successful Git run completes the transition when it matches the + recorded repository, production branch, and root directory and actually + dispatches every recorded resource. Ordinary production-branch pushes + deploy without changing a platform-managed project's source ownership. security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - name: limit - in: query - description: Maximum number of queries to return. - schema: - type: integer - minimum: 1 - maximum: 100 - default: 10 responses: '200': - description: Database query performance retrieved - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseQueryPerformanceResponse' - '400': - description: Bad request - invalid query parameters + description: The project's source-of-truth state content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ProjectSourceExportState' '401': description: Unauthorized - invalid or missing token content: @@ -2291,13 +2475,13 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Access denied + description: Forbidden - project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project or database not found + description: Project not found content: application/json: schema: @@ -2308,86 +2492,60 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /deployments: - get: + '501': + description: Source export is not available in this deployment mode + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: tags: - Projects - summary: List deployments across a user's projects + - Git Connections + summary: Initialize an empty repository with a project's stored source + operationId: exportProjectSource description: | - Lists Function and Frontend deployment attempts across every project the - user owns, newest first. Pass `project_id` to narrow the feed to a single - project. - - Scope is project **ownership** (`projects.user_id`). `owner_id` names - whose deployments to return, not who started them — the actor is - `initiated_by_user_id`, which this endpoint does not filter on. - - With a user token the scope is always the authenticated user: `owner_id` - may be omitted, or set to that same user, but naming anyone else is - refused with 403. Service callers on the management API must pass it, - since they have no authenticated user. - - The owner is not checked for existence: an id with no projects returns an - empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is - polled to detect an event, so a caller needs `404` to keep meaning "this - route is not served here" — which is how a consumer notices it is running - against an older release. A mistyped owner therefore reads as "nothing - deployed"; callers that need to tell those apart should verify the user - through `GET /users/{id}` first. + Creates the first commit in the connected repository and pushes it + directly to the configured production branch. The push enters the + ordinary Git auto-deploy flow. Direct source writes remain frozen until + that deployment succeeds and the repository becomes the source of truth. - Ordering is selectable. The default is the feed order — most recent - attempt first. `completed_at.asc` orders by completion, oldest first, and - considers only attempts that finished; combined with `limit=1` and a - `status` filter it answers "when did this user first succeed" in one - bounded query. + The caller confirms the production branch shown before export. Starting + export pins that branch: later GitHub default-branch changes do not + repoint the project. If the configured branch changed after the caller + read it, the request fails without exporting so the caller can show and + confirm the new value. - Both pagination modes are supported, selected exactly as - `/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a - `limit` with no `page`) uses keyset pagination; otherwise `page`/`limit` - offset pagination. `page` with a cursor, and `cursor` with - `ending_before`, are rejected. + The response lists what the export could not carry: resources with no + successful deployment to take source from (`skipped`), and things no + export can hand back (`omitted`) — migrations, which Volcano stores no + copy of, and credential-shaped files, which are left for their owner to + add. - A cursor is bound to every filter *and* to `order`, so changing any of - them mid-pagination rejects the cursor rather than silently skipping or - repeating rows. The keyset position is `(created_at, id)` for - `created_at.desc` and `(completed_at, id)` for `completed_at.asc`. - operationId: listDeployments + Requires a connected repository with no commits or branches, and runs + once. Volcano never creates the repository. If GitHub did not confirm + the push, retrying creates the same commit and adopts it when it already + reached the repository. security: - UserToken: [] + - ProjectAccessToken: [] parameters: - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/DeploymentOwnerId' - - name: project_id - in: query - required: false - description: Restrict the feed to a single project owned by the user. - schema: - type: string - format: uuid - - name: created_after - in: query - required: false - description: Restrict results to attempts created at or after this timestamp. - schema: - type: string - format: date-time - - $ref: '#/components/parameters/DeploymentResourceType' - - $ref: '#/components/parameters/DeploymentStatus' - - $ref: '#/components/parameters/DeploymentOperation' - - $ref: '#/components/parameters/DeploymentOrder' + - $ref: '#/components/parameters/ProjectId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExportProjectSourceRequest' responses: - '200': - description: Successful response + '201': + description: The initial production-branch commit that was pushed content: application/json: schema: - $ref: '#/components/schemas/PaginatedProjectDeployments' + $ref: '#/components/schemas/ProjectSourceExport' '400': - description: Bad request - invalid filter or pagination + description: Malformed request body content: application/json: schema: @@ -2399,7 +2557,38 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Forbidden - owner_id names a different user + description: Forbidden - project not owned by the caller + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Project not found, or it has no repository connected + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: | + The source has already been exported, the repository has already + taken over as the source of truth, the confirmed production branch + is stale, a function or frontend deployment is still in progress, + or the project has no stored source to export + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '422': + description: | + The repository refused the branch, or its contents cannot be laid + out as a repository — a stored file that only ever carries + credentials, or a layout Git auto-deploy would not read back + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: GitHub rate limited the request content: application/json: schema: @@ -2410,66 +2599,57 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/deployments: - get: + '501': + description: Source export is not available in this deployment mode + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: GitHub integration is not configured + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: tags: - Projects - summary: List deployments in a project + - Git Connections + summary: Cancel an incomplete source export + operationId: cancelProjectSourceExport description: | - Lists Function and Frontend deployment attempts across the project, - ordered most-recent first. Each item includes a normalized resource - reference so clients can render both resource types without extra - fetches. - operationId: listProjectDeployments + Restores platform source writes while the project is in + `git_exporting` or `git_pending`. If Volcano reserved or deployed the + root commit, export remains consumed and cannot be run again. The + connected repository and any commit already pushed to it are unchanged. security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' - - name: created_after - in: query - required: false - description: Restrict results to attempts created at or after this timestamp. - schema: - type: string - format: date-time - - name: resource_type - in: query - required: false - description: | - Restrict the feed to a single resource type. Omit to return both - Function and Frontend deployments. - schema: - type: string - enum: - - function - - frontend responses: - '200': - description: Successful response + '204': + description: The incomplete source transition was canceled + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: - $ref: '#/components/schemas/PaginatedProjectDeployments' - '400': - description: Bad request - invalid identifier + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + '404': + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required + '409': + description: No incomplete transition exists, or Git already took ownership content: application/json: schema: @@ -2480,54 +2660,55 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/deployments/summary: - get: + '501': + description: Source export is not available in this deployment mode + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/git-connection/production-branch: + put: tags: - Projects - summary: Summarize deployments in a project + - Git Connections + summary: Set the branch a project deploys from description: | - Summarizes deployment attempts for one comparable resource pipeline. - Success rate uses conclusive outcomes only: active and deleted attempts - are successful; failed and degraded attempts are failures; in-progress - and superseded attempts are excluded. Median build duration includes - completed, non-superseded attempts with recorded build work, - including failed builds. - operationId: summarizeProjectDeployments + Changes only the production branch, leaving the repository binding + alone. PUT /projects/{id}/git-connection can also set it, but that is a + full rebind: it needs connection_id, installation_id and a repository + selector resent, and re-resolves the repository against GitHub for a + field that does not depend on it. + + The branch does not have to exist. It is validated as a Git branch name + and nothing more, so a project can be pointed at a branch that is about + to be pushed — the case a repository created empty depends on. + + Setting the branch here marks it as the project's own choice, so a later + default-branch rename on GitHub no longer moves it. Projects that never + set one keep following the repository's default branch. + operationId: setProjectGitProductionBranch security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: search - in: query - required: false - description: Restrict the summary to resource names containing this value. - schema: - type: string - - name: resource_type - in: query - required: true - description: Restrict the summary to one comparable deployment pipeline. - schema: - type: string - enum: - - function - - frontend - - name: created_after - in: query - required: false - description: Restrict results to attempts created at or after this timestamp. - schema: - type: string - format: date-time + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SetProjectGitProductionBranchRequest' responses: '200': - description: Successful response + description: The project's repo connection, with the new branch content: application/json: schema: - $ref: '#/components/schemas/ProjectDeploymentSummary' + $ref: '#/components/schemas/ProjectGitConnection' '400': - description: Bad request - invalid identifier or filter + description: | + Malformed request body, or a production_branch that is not a valid + Git branch name content: application/json: schema: @@ -2539,440 +2720,468 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Forbidden - project ownership required + description: Project not owned by the caller + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: | + Project not found, or it has no repository connected. The branch is + part of the connection, so there is nothing to set it on until one + exists. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: A Git source transition is pending content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Internal server error + description: Failed to set the production branch content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/domains: + /projects/{id}/git-connection: get: tags: - - Frontends - summary: List all custom domains in a project - description: | - Project-scoped custom-domain list. Returns every active custom - domain across every frontend in the project (excludes soft-deleted - rows). Each item inlines the linked frontend's id and name so the - UI does not need a second fetch to render the "Linked to" column. - operationId: listProjectCustomDomains + - Projects + - Git Connections + summary: Get a project's repo connection + operationId: getProjectGitConnection security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' responses: '200': - description: Successful response + description: The project's current repo connection content: application/json: schema: - $ref: '#/components/schemas/PaginatedProjectCustomDomains' - '400': - description: Bad request - invalid identifier + $ref: '#/components/schemas/ProjectGitConnection' + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + '403': + description: Project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required + '404': + description: Project not found, or has no repo connection content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Internal server error + description: Failed to get project git connection content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/functions: - get: + put: tags: - - Functions - summary: List all functions in a project + - Projects + - Git Connections + summary: Connect or update a project's repo connection description: | - Supports two mutually exclusive pagination modes. Offset mode uses `page` - and `limit` and returns `next` (URL). Cursor mode uses `cursor` and - `limit`, supports `search` (case-insensitive name match), and returns - `next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page` - and `search`) returns 400. - operationId: listFunctions + Full replace, following Vercel's model: many projects may point at the + same repo, so this only binds the project — it never creates or + deletes git-provider state. Used for both the initial connect and + later edits (repo change, root directory, production branch). + Resolves the repository_id or repo_full_name selector against the repos + accessible through installation_id via connection_id's stored GitHub + user token, then persists repository metadata only from that validated + GitHub response. + operationId: connectProjectGit security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectProjectGitRequest' responses: '200': - description: Successful response + description: The project's repo connection content: application/json: schema: - $ref: '#/components/schemas/PaginatedFunctions' + $ref: '#/components/schemas/ProjectGitConnection' + '400': + description: | + Malformed request body, no repository selector, selectors that + identify different repositories, a production_branch that is not a + valid Git branch name, no production_branch on a repository with no + default branch to follow (name one to connect a repository that has + no commits yet), or a production_branch other than the new + repository's default in a request that also changes repository. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: | + Project not owned by the caller, or the selected repository is not + accessible through installation_id + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Project not found + description: Project or connection not found content: application/json: schema: $ref: '#/components/schemas/Error' - post: + '409': + description: | + A Git source transition is pending or complete, so the recorded + repository and root cannot be changed + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Failed to connect project git + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Git provider integration is not configured + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: tags: - - Functions - summary: Create or update function code - description: | - Upload a serverless function source bundle. Direct API clients may send the function code - as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz - source archive. - Cloud deploys should include source files and dependency manifests/lockfiles, not installed - dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the - function compile build. - Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI - does not apply its own source archive size limit. After the final container image is - built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. - Uploaded source archives cannot contain symlink entries. Safe symlinks created during - the cloud build are materialized before publish. - Volcano builds and deploys the function asynchronously after upload. A deployment that starts - immediately returns a Function resource with `status: provisioning`, then transitions to - `active` or `failed`. If another deployment is running, the response preserves the resource's - current status and exposes the queued deployment through `pending_deployment_id`. - Existing function traffic continues to use the last known-good runtime during an update. A failed - update keeps that runtime available and records the attempted deployment as failed. - Only one deployment runs for a given function. A newer request supersedes any queued request - and starts after the running deployment. Different functions and projects deploy concurrently. - If a function with the same name already exists in the project, this operation updates that - function's runtime, handler, and source bundle and returns `200 OK`. - Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403. - operationId: createFunction + - Projects + - Git Connections + summary: Disconnect a project's repo connection + operationId: disconnectProjectGit security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - required: - - name - - code - - runtime - properties: - name: - type: string - description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) - maxLength: 63 - pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ - example: my-api-function - code: - type: string - format: binary - description: ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz source archive. - runtime: - type: string - enum: - - nodejs22.x - - nodejs24.x - - python3.10 - - python3.11 - - python3.12 - - python3.13 - - python3.14 - - ruby3.3 - - ruby3.4 - - ruby4.0 - description: | - Runtime environment. Required. - - Node.js: nodejs22.x, nodejs24.x - - Python: python3.10, python3.11, python3.12, python3.13, python3.14 - - Ruby: ruby3.3, ruby3.4, ruby4.0 - example: nodejs24.x - handler: - type: string - description: | - The name of the function to invoke. Defaults to "handler" if not specified. - Your code must export/define a function with this name: - - Node.js: exports.handler (in index.js) - - Python: def handler() (in main.py) - - Ruby: def handler() (in main.rb) - default: handler - example: handler - is_public: - type: boolean - description: | - Whether the function can be reached through public invocation - ingress. Omit it to keep the function's current visibility; a - new function starts private. - invocation_mode: - $ref: '#/components/schemas/FunctionInvocationMode' - http_auth_mode: - $ref: '#/components/schemas/FunctionHTTPAuthMode' - openapi_spec: - type: string - description: JSON-encoded OpenAPI 3.0 or 3.1 metadata for an HTTP-mode function. - variable_scope: - type: string - enum: - - all - - scoped - description: | - Which project variables this function receives. `all` (the default) gives it only project variables marked `shared: true`; `scoped` gives it only the variables it selects. Omitting this leaves an existing function's scope unchanged. - variables: - type: string - description: | - JSON-encoded array of project variable names this function requires, on top of the ones detected in its source. A declared name the project does not define is rejected with 400; a detected name it does not define is ignored. Only used when `variable_scope` is `scoped`. Omitting this leaves an existing function's declared names unchanged. responses: - '200': - description: Existing function updated; its deployment was started or queued - content: - application/json: - schema: - $ref: '#/components/schemas/Function' - '201': - description: Function created and deployment workflow started + '204': + description: Connection removed + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: - $ref: '#/components/schemas/Function' - '400': - description: Bad request (invalid file, too large, etc.) + $ref: '#/components/schemas/Error' + '403': + description: Project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Function limit exceeded for the project + '404': + description: Project not found, or has no repo connection content: application/json: schema: $ref: '#/components/schemas/Error' '409': description: | - Function deletion is queued or running, or the name is already held - by a durable function — a function cannot change kind. + A Git source transition is pending or complete, so the recorded + repository cannot be disconnected content: application/json: schema: $ref: '#/components/schemas/Error' '500': - description: Internal server error (function deployment failed) + description: Failed to disconnect project git content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/functions/{functionId}: + /projects/{id}/git-deploy-settings: get: tags: - - Functions - summary: Get function by ID - operationId: getFunction + - Projects + - Git Connections + summary: Get a project's Git auto-deploy settings + operationId: getProjectGitDeploySettings security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' responses: '200': - description: Successful response + description: The project's current Git auto-deploy settings content: application/json: schema: - $ref: '#/components/schemas/Function' + $ref: '#/components/schemas/ProjectGitDeploySettings' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Project not owned by the caller + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Function not found + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - patch: + '500': + description: Failed to get project git deploy settings + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + put: tags: - - Functions - summary: Update function settings - operationId: updateFunction + - Projects + - Git Connections + summary: Update a project's Git auto-deploy settings + description: | + Full replace of the project's Git auto-deploy settings: what a push to + the connected repo's production branch deploys. + + Connecting a repository sets auto_deploy_enabled and deploy_functions + to true for a project that has never called this endpoint, so a push + deploys without any further setup. Once these settings have been saved + here they are the project's own: connecting, rebinding, disconnecting + and reconnecting all leave them untouched, including when they were + saved before any repository was connected. Frontend settings are off + until set here; the frontend need not exist when they are saved, since + frontend_name is resolved at deploy time. + operationId: updateProjectGitDeploySettings security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/UpdateFunctionRequest' - examples: - makePublic: - summary: Make function public (anon keys can invoke) - value: - is_public: true - makePrivate: - summary: Make function private (default behavior) - value: - is_public: false + $ref: '#/components/schemas/UpdateProjectGitDeploySettingsRequest' responses: '200': - description: Function updated + description: The project's updated Git auto-deploy settings content: application/json: schema: - $ref: '#/components/schemas/Function' + $ref: '#/components/schemas/ProjectGitDeploySettings' '400': - description: Bad request + description: Malformed request body, or frontend_app_root without frontend_name + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Function not found + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + '409': + description: | + A Git source transition is pending, or this change would remove + deploy coverage after Git has taken over + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Failed to update project git deploy settings + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/databases/{databaseName}/queries: + get: tags: - - Functions - summary: Delete a function + - Databases + summary: Get database queries description: | - Schedules asynchronous function deletion. If another deployment is running, the function - preserves its current status and exposes the queued deletion through `pending_deployment_id`. - Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no - longer appears in function lists. - operationId: deleteFunction + Returns the database's current top queries from pg_stat_statements + ranked by total execution time. Only data statements (SELECT, INSERT, + UPDATE, DELETE, MERGE) are listed; statements Volcano runs to operate + the database are left out. + + **SUPERAGENT plan required.** This endpoint is only available to projects owned + by users on the SUPERAGENT billing plan. + operationId: getProjectDatabaseQueries security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' + - $ref: '#/components/parameters/DatabaseName' + - name: limit + in: query + description: Maximum number of queries to return. + schema: + type: integer + minimum: 1 + maximum: 100 + default: 10 responses: - '202': - description: Function deletion started or queued + '200': + description: Database query performance retrieved + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseQueryPerformanceResponse' + '400': + description: Bad request - invalid query parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Access denied + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Function not found + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' - /functions/{functionId}/invoke: - post: - tags: - - Functions - summary: Invoke a function - description: | - Invoke a serverless function. - - **With Service Key** (admin/background operations): - - Use for background jobs, webhooks, cron, admin operations - - Function receives payload only (no user context) - - Database queries bypass RLS (admin access) + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /deployments: + get: + tags: + - Projects + summary: List deployments across a user's projects + description: | + Lists Function and Frontend deployment attempts across every project the + user owns, newest first. Pass `project_id` to narrow the feed to a single + project. - **With Auth User Token** (user-facing): - - Use for user-initiated actions - - Function receives payload + `__volcano_auth` context: - ```javascript - { - user_id: "uuid", - email: "user@example.com", - project_id: "uuid", - role: "authenticated" or "anonymous" - } - ``` - - Database queries enforce RLS (user-scoped data) + Scope is project **ownership** (`projects.user_id`). `owner_id` names + whose deployments to return, not who started them — the actor is + `initiated_by_user_id`, which this endpoint does not filter on. - **With Anon Key** (public function only): - - Requires anon key permission: `functions.invoke` - - Function must have `is_public: true` - - Function receives payload only (no `__volcano_auth`) + With a user token the scope is always the authenticated user: `owner_id` + may be omitted, or set to that same user, but naming anyone else is + refused with 403. Service callers on the management API must pass it, + since they have no authenticated user. - **Transport and CORS:** - - This operation is the authenticated direct RPC endpoint and always uses the - POST `{payload: ...}` contract, including for functions whose DNS ingress is - configured in HTTP mode. - - The geo-routed DNS ingress is `https://{functionId}.functions./`. - - RPC-mode DNS ingress accepts POST at `/`. HTTP-mode DNS ingress accepts GET, - HEAD, POST, PUT, PATCH, and DELETE at `/` and nested paths. - - Direct and RPC-mode CORS preflight advertises `POST, OPTIONS`. HTTP-mode DNS - preflight advertises `GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`. - - `http_auth_mode: none` applies only to public HTTP-mode DNS ingress; this - direct operation always requires a Volcano credential. + The owner is not checked for existence: an id with no projects returns an + empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is + polled to detect an event, so a caller needs `404` to keep meaning "this + route is not served here" — which is how a consumer notices it is running + against an older release. A mistyped owner therefore reads as "nothing + deployed"; callers that need to tell those apart should verify the user + through `GET /users/{id}` first. - **Durable functions are not invocable here.** A durable function's id - answers 404, whatever its visibility, because a synchronous call would - run it with no execution record, no idempotency and no concurrency - accounting. Start one with - `POST /durable-functions/{functionId}/executions`. - operationId: invokeFunction + Ordering is selectable. The default is the feed order — most recent + attempt first. `completed_at.asc` orders by completion, oldest first, and + considers only attempts that finished; combined with `limit=1` and a + `status` filter it answers "when did this user first succeed" in one + bounded query. + + Both pagination modes are supported, selected exactly as + `/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a + `limit` with no `page`) uses keyset pagination; otherwise `page`/`limit` + offset pagination. `page` with a cursor, and `cursor` with + `ending_before`, are rejected. + + A cursor is bound to every filter *and* to `order`, so changing any of + them mid-pagination rejects the cursor rather than silently skipping or + repeating rows. The keyset position is `(created_at, id)` for + `created_at.desc` and `(completed_at, id)` for `completed_at.asc`. + operationId: listDeployments security: - - AnonKey: [] - - ServiceRoleKey: [] - - AuthUserAccessToken: [] + - UserToken: [] parameters: - - $ref: '#/components/parameters/FunctionId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/FunctionInvocationRequest' - examples: - serviceCall: - summary: Admin/background operation (service key) - value: - payload: - action: process_batch - items: - - 1 - - 2 - - 3 - userCall: - summary: User-initiated call (auth token) - value: - payload: - action: get_profile - anonCall: - summary: Public function call (anon key) - value: - payload: - action: ping_public_endpoint + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/DeploymentOwnerId' + - name: project_id + in: query + required: false + description: Restrict the feed to a single project owned by the user. + schema: + type: string + format: uuid + - name: created_after + in: query + required: false + description: Restrict results to attempts created at or after this timestamp. + schema: + type: string + format: date-time + - $ref: '#/components/parameters/DeploymentResourceType' + - $ref: '#/components/parameters/DeploymentStatus' + - $ref: '#/components/parameters/DeploymentOperation' + - $ref: '#/components/parameters/DeploymentOrder' responses: '200': - description: Function response (passthrough from function runtime) - headers: - X-Volcano-Version: - description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production) - schema: - type: string - X-Volcano-Region: - description: Region the function ran in (for example `us-east-1`) - schema: - type: string + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/FunctionInvocationResponse' + $ref: '#/components/schemas/PaginatedProjectDeployments' '400': - description: Bad request - invalid payload or function in failed state + description: Bad request - invalid filter or pagination content: application/json: schema: @@ -2984,237 +3193,190 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Forbidden - CORS blocked, missing `functions.invoke`, or private function with anon key + description: Forbidden - owner_id names a different user content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Function not found + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' - '429': + /projects/{id}/deployments: + get: + tags: + - Projects + summary: List deployments in a project + description: | + Lists Function and Frontend deployment attempts across the project, + ordered most-recent first. Each item includes a normalized resource + reference so clients can render both resource types without extra + fetches. + operationId: listProjectDeployments + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + - name: created_after + in: query + required: false + description: Restrict results to attempts created at or after this timestamp. + schema: + type: string + format: date-time + - name: resource_type + in: query + required: false description: | - Rate limit exceeded (per-function or project-wide limit), or the - owning platform user's billing-cycle bandwidth allowance (aggregate ingress + - egress) was exceeded. + Restrict the feed to a single resource type. Omit to return both + Function and Frontend deployments. + schema: + type: string + enum: + - function + - frontend + responses: + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': - description: | - Function still provisioning or rate limiting service unavailable. - A freshly deployed (or updated) function may briefly report - `provisioning` and reject invocations until the background status - reconciler observes its deployment workflow completing and transitions - it to `active`. This is expected for a few seconds after deploy; clients - should retry. + $ref: '#/components/schemas/PaginatedProjectDeployments' + '400': + description: Bad request - invalid identifier content: application/json: schema: $ref: '#/components/schemas/Error' - default: - description: Function response (passthrough; status code/body/headers come from the function) - headers: - X-Volcano-Version: - description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production) + '401': + description: Unauthorized - invalid or missing token + content: + application/json: schema: - type: string - X-Volcano-Region: - description: Region the function ran in (for example `us-east-1`) + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - project ownership required + content: + application/json: schema: - type: string + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: - $ref: '#/components/schemas/FunctionInvocationResponse' - /durable-functions/{functionId}/executions: - post: + $ref: '#/components/schemas/Error' + /projects/{id}/deployments/summary: + get: tags: - - Durable Functions - summary: Start a durable execution from an application + - Projects + summary: Summarize deployments in a project description: | - Starts an execution of a durable function using an application - credential, and returns its handle. - - This is the durable counterpart of `POST /functions/{functionId}/invoke`, - and it is the endpoint an application calls. Like that one, it is not - project-scoped: an anon key, a service key and an auth user token each - carry their own project. The project-scoped collection under - `/projects/{id}/durable-functions/...` remains the owner's management - surface. - - **With a service key or an auth user token:** any durable function in - the project. - - **With an anon key:** requires the `functions.invoke` permission, and - the function must have `is_public: true`. - - Starting is all this endpoint does. Reading a result or stopping an - execution requires the project owner's token, because an anon key is - shared by everyone who loads the page and an execution is addressed by - id alone. - - Send `X-Volcano-Execution-Name` to make the start idempotent: repeating - a start with the same name returns the existing execution instead of - beginning a second one. - - Each execution counts once against the project's durable execution - allowance, however many times the start is retried under the same - execution name, and the number in flight at once is capped by the plan. - The operations the execution performs are counted against the durable - operations allowance when it finishes. - operationId: startDurableExecutionFromApplication + Summarizes deployment attempts for one comparable resource pipeline. + Success rate uses conclusive outcomes only: active and deleted attempts + are successful; failed and degraded attempts are failures; in-progress + and superseded attempts are excluded. Median build duration includes + completed, non-superseded attempts with recorded build work, + including failed builds. + operationId: summarizeProjectDeployments security: - - AnonKey: [] - - ServiceRoleKey: [] - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - $ref: '#/components/parameters/DurableFunctionId' - - name: X-Volcano-Execution-Name - in: header + - $ref: '#/components/parameters/ProjectId' + - name: search + in: query required: false - description: | - Idempotency key for this execution. Generated when omitted. A repeat - under a name that already names a running execution returns that - execution and is not charged again. - - Letters, digits, `-`, `_` and `.`, up to 255 characters. Anything - else is rejected with `400`. + description: Restrict the summary to resource names containing this value. schema: type: string - maxLength: 255 - pattern: ^[A-Za-z0-9._-]+$ - requestBody: - required: false - content: - application/json: - schema: - description: Input passed to the function, up to 256 KiB. + - name: resource_type + in: query + required: true + description: Restrict the summary to one comparable deployment pipeline. + schema: + type: string + enum: + - function + - frontend + - name: created_after + in: query + required: false + description: Restrict results to attempts created at or after this timestamp. + schema: + type: string + format: date-time responses: - '202': - description: Execution accepted and started + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DurableExecution' + $ref: '#/components/schemas/ProjectDeploymentSummary' '400': - description: Payload is not valid JSON, or the execution name is invalid + description: Bad request - invalid identifier or filter content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: | - Missing or invalid credential. Also returned for a platform user - token, which is not an application credential; project owners start - executions through the project-scoped collection. + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: | - The anon key lacks `functions.invoke`, the function is not public, - or the request's origin is refused by the project's CORS policy. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: | - Durable function not found. Also returned for a standard function's - id and for a durable function in another project, so the response - cannot be used to tell those apart. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: | - Function is not deployed yet, or has no deployed region. Also - returned when two starts under the same execution name raced and - both released it, which is retryable as it stands. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '413': - description: Payload is larger than 256 KiB - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '429': - description: | - The project has too many executions in flight for its plan, the - function invocation rate limit was exceeded, the project is over - its bandwidth cap, or the account is out of one of its - billing-cycle durable allowances: executions, operations, or - compute. Operations and compute are counted once an execution - finishes, so a refusal on either never interrupts an execution - already running — it declines the next start. + description: Forbidden - project ownership required content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: | - Durable execution is not available in this environment, or the - usage limit service could not be reached to charge the start. The - first is returned by a deployment that has no durable execution - engine, such as a local one, and is not retryable there; the second - is transient. + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' - /functions/resolve: + /projects/{id}/domains: get: tags: - - Functions - summary: Resolve function name for invocation + - Frontends + summary: List all custom domains in a project description: | - Resolves a DNS-safe function name to its function ID within the caller's project. - - SDKs use this endpoint internally to invoke by function name while routing by function ID. - - **With Service Key**: - - Allowed - - **With Auth User Token**: - - Allowed - - **With Anon Key**: - - Requires anon key permission: `functions.invoke` - - Function must have `is_public: true` - operationId: resolveFunctionForInvocation + Project-scoped custom-domain list. Returns every active custom + domain across every frontend in the project (excludes soft-deleted + rows). Each item inlines the linked frontend's id and name so the + UI does not need a second fetch to render the "Linked to" column. + operationId: listProjectCustomDomains security: - - AnonKey: [] - - ServiceRoleKey: [] - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - name: name - in: query - required: true - schema: - type: string - maxLength: 63 - pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ - description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) - example: my-function + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' responses: '200': - description: Function resolved successfully + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/ResolveFunctionResponse' + $ref: '#/components/schemas/PaginatedProjectCustomDomains' '400': - description: Bad request - missing or invalid function name + description: Bad request - invalid identifier content: application/json: schema: @@ -3226,827 +3388,1101 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Forbidden - CORS blocked or missing `functions.invoke` permission for anon key + description: Forbidden - project ownership required content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: | - Function not found (or private function with anon key). A durable - function is never resolvable here: it is started through - `POST /durable-functions/{functionId}/executions`, not invoked. + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/logs/activity: - post: + /projects/{id}/functions: + get: tags: - - Logs - summary: Get project log activity + - Functions + summary: List all functions in a project description: | - Retrieve bucketed log counts for one resource type in the project. Set - `resource.type` to `function`, `frontend`, or `database`. Add - `resource.ids` to filter to one or more resources, and add - `resource.deployments.ids` to count deployment logs instead of runtime - logs for functions and frontends. Deployment logs are not supported for - databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database` - from a HOBBY-plan project owner returns 403. The activity window is limited - to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older start - times are clamped to that window. - operationId: getProjectLogActivity + Supports two mutually exclusive pagination modes. Offset mode uses `page` + and `limit` and returns `next` (URL). Cursor mode uses `cursor` and + `limit`, supports `search` (case-insensitive name match), and returns + `next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page` + and `search`) returns 400. + operationId: listFunctions security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/LogActivityRequest' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/LogActivityResponse' - '400': - description: Bad request - invalid query parameter - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/PaginatedFunctions' '404': - description: Project or resource not found + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/logs/search: post: tags: - - Logs - summary: Search project logs + - Functions + summary: Create or update function code description: | - Search or filter logs for one resource type in the project. Set - `resource.type` to `function`, `frontend`, or `database`. Add - `resource.ids` to filter to one or more resources, and add - `resource.deployments.ids` to read deployment logs instead of runtime - logs for functions and frontends. Deployment logs are not supported for - databases. Database logs are a SUPERAGENT-plan feature; requests for - `resource.type=database` from a HOBBY-plan project owner return 403. - Log history (runtime and deployment) is limited to the plan's retention - window (HOBBY: 1 day, SUPERAGENT: 30 days); older time ranges are clamped to that - window. - operationId: searchProjectLogs - security: + Upload a function source bundle. Direct API clients may send the function code + as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz + source archive. + Cloud deploys should include source files and dependency manifests/lockfiles, not installed + dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the + function compile build. + Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI + does not apply its own source archive size limit. After the final container image is + built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. + Uploaded source archives cannot contain symlink entries. Safe symlinks created during + the cloud build are materialized before publish. + Volcano builds and deploys the function asynchronously after upload. A deployment that starts + immediately returns a Function resource with `status: provisioning`, then transitions to + `active` or `failed`. If another deployment is running, the response preserves the resource's + current status and exposes the queued deployment through `pending_deployment_id`. + Existing function traffic continues to use the last known-good runtime during an update. A failed + update keeps that runtime available and records the attempted deployment as failed. + Only one deployment runs for a given function. A newer request supersedes any queued request + and starts after the running deployment. Different functions and projects deploy concurrently. + If a function with the same name already exists in the project, this operation updates that + function's runtime, handler, and source bundle and returns `200 OK`. + Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403. + operationId: createFunction + security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: - application/json: + multipart/form-data: schema: - $ref: '#/components/schemas/LogSearchRequest' + type: object + required: + - name + - code + - runtime + properties: + name: + type: string + description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) + maxLength: 63 + pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ + example: my-api-function + code: + type: string + format: binary + description: ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz source archive. + runtime: + type: string + enum: + - nodejs22.x + - nodejs24.x + - python3.10 + - python3.11 + - python3.12 + - python3.13 + - python3.14 + - ruby3.3 + - ruby3.4 + - ruby4.0 + description: | + Runtime environment. Required. + - Node.js: nodejs22.x, nodejs24.x + - Python: python3.10, python3.11, python3.12, python3.13, python3.14 + - Ruby: ruby3.3, ruby3.4, ruby4.0 + example: nodejs24.x + handler: + type: string + description: | + The name of the function to invoke. Defaults to "handler" if not specified. + Your code must export/define a function with this name: + - Node.js: exports.handler (in index.js) + - Python: def handler() (in main.py) + - Ruby: def handler() (in main.rb) + default: handler + example: handler + is_public: + type: boolean + description: | + Whether the function can be reached through public invocation + ingress. Omit it to keep the function's current visibility; a + new function starts private. + invocation_mode: + $ref: '#/components/schemas/FunctionInvocationMode' + http_auth_mode: + $ref: '#/components/schemas/FunctionHTTPAuthMode' + openapi_spec: + type: string + description: JSON-encoded OpenAPI 3.0 or 3.1 metadata for an HTTP-mode function. + variable_scope: + type: string + enum: + - all + - scoped + x-enum-varnames: + - CreateFunctionMultipartBodyVariableScopeAll + - CreateFunctionMultipartBodyVariableScopeScoped + description: | + Which project variables this function receives. `all` (the default) gives it only project variables marked `shared: true`; `scoped` gives it only the variables it selects. Omitting this leaves an existing function's scope unchanged. + variables: + type: string + description: | + JSON-encoded array of project variable names this function requires, on top of the ones detected in its source. A declared name the project does not define is rejected with 400; a detected name it does not define is ignored. Only used when `variable_scope` is `scoped`. Omitting this leaves an existing function's declared names unchanged. responses: '200': - description: Successful response + description: Existing function updated; its deployment was started or queued content: application/json: schema: - $ref: '#/components/schemas/LogSearchResponse' + $ref: '#/components/schemas/Function' + '201': + description: Function created and deployment workflow started + content: + application/json: + schema: + $ref: '#/components/schemas/Function' '400': - description: Bad request - invalid query parameter + description: Bad request (invalid file, too large, etc.) content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + '403': + description: Function limit exceeded for the project content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required + '409': + description: | + Function deletion is queued or running, or the name is already held + by a durable function — a function cannot change kind. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: | + The owner's billing-cycle build-minutes allowance is spent. The + error names the allowance and carries a link to the usage page. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error (function deployment failed) + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: | + Build usage could not be read, so the allowance could not be + checked. The same request succeeds once it can be. content: application/json: schema: $ref: '#/components/schemas/Error' + /projects/{id}/functions/{functionId}: + get: + tags: + - Functions + summary: Get function by ID + operationId: getFunction + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/FunctionId' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/Function' '404': - description: Project or resource not found + description: Function not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/logs/stream: - post: + patch: tags: - - Logs - summary: Stream project logs - description: | - Live-tail project logs as Server-Sent Events. The request body uses the - resource selector plus `q`, `start_time`, and `limit`, - including runtime logs and function/frontend deployment logs selected - with `resource.deployments`. Deployment logs are not supported for - databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database` - from a HOBBY-plan project owner returns 403. The `q` field uses the same - syntax as search and activity requests. Do not send `cursor` or - `end_time`; use `/logs/search` for range backfills. - Explicit historical `start_time` values are limited to the plan's - retention window (HOBBY: 1 day, SUPERAGENT: 30 days). Resume with - `Last-Event-ID` or the `last_event_id` query parameter. The cursor is - bound to the request body: the resource selector and every filter must - match the original request when reconnecting, otherwise the request is - rejected with `400`. - - This is a live tail, not a gap-free backfill. On connect or reconnect the - server delivers at most `limit` of the most recent matching events from - the cursor position and then follows new events; events older than that - window are not replayed. Use `/logs/search` to backfill a time range. - operationId: streamProjectLogs + - Functions + summary: Update function settings + operationId: updateFunction security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: Last-Event-ID - in: header - required: false - schema: - type: string - description: Opaque stream cursor from the most recent SSE `id` field. - - name: last_event_id - in: query - required: false - schema: - type: string - description: Opaque stream cursor fallback when setting `Last-Event-ID` is not practical. + - $ref: '#/components/parameters/FunctionId' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/LogStreamRequest' + $ref: '#/components/schemas/UpdateFunctionRequest' + examples: + makePublic: + summary: Make function public (anon keys can invoke) + value: + is_public: true + makePrivate: + summary: Make function private (default behavior) + value: + is_public: false responses: '200': - description: Server-Sent Events stream. `log` events contain a JSON `LogSearchEvent`; `warning` events contain a JSON object with an `error` field. + description: Function updated content: - text/event-stream: + application/json: schema: - type: string - examples: - log: - summary: Log event - value: | - : connected - - id: STREAM_CURSOR - event: log - data: {"id":"LOG_EVENT_ID","timestamp":"2024-01-01T12:00:00Z","level":"info","message":"User logged in","resource":{"type":"function","id":"550e8400-e29b-41d4-a716-446655440000","name":"login"},"region":"us-east-1"} + $ref: '#/components/schemas/Function' '400': - description: Bad request - invalid selector, stream cursor, or unsupported stream field + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + '404': + description: Function not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required + '409': + description: Function settings conflict with attached Frontend Function routes content: application/json: schema: $ref: '#/components/schemas/Error' + delete: + tags: + - Functions + summary: Delete a function + description: | + Schedules asynchronous function deletion. If another deployment is running, the function + preserves its current status and exposes the queued deletion through `pending_deployment_id`. + Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no + longer appears in function lists. + operationId: deleteFunction + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/FunctionId' + responses: + '202': + description: Function deletion started or queued '404': - description: Project or resource not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - log streaming setup failed + description: Function not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/functions/batch: + /functions/{functionId}/invoke: post: tags: - Functions - summary: Deploy multiple functions in one request + summary: Invoke a function description: | - Upload multiple function source archives in one multipart request. Each archive should contain source files - plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads are - accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB` - for each uploaded and normalized source archive. The server records a shared - deployment batch ID for the resulting function deployments. Each function deployment runs its own - compile/publish workflow concurrently, and each publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` - for the final container image. - One batch request can include up to 100 functions. Submit multiple batch requests for larger projects. - If one function fails before its workflow starts, already-started function deployments are left - running and the failed function is reported in the `failed` array. Failed new functions are deleted; - failed updates are rolled back to their previous metadata/status where possible. - operationId: createFunctionsBatch + Invoke a function. + + **With Service Key** (admin/background operations): + - Use for background jobs, webhooks, cron, admin operations + - Function receives payload only (no user context) + - Database queries bypass RLS (admin access) + + **With Auth User Token** (user-facing): + - Use for user-initiated actions + - Function receives payload + `__volcano_auth` context: + ```javascript + { + user_id: "uuid", + email: "user@example.com", + project_id: "uuid", + role: "authenticated" or "anonymous" + } + ``` + - Database queries enforce RLS (user-scoped data) + + **With Anon Key** (public function only): + - Requires anon key permission: `functions.invoke` + - Function must have `is_public: true` + - Function receives payload only (no `__volcano_auth`) + + **Transport and CORS:** + - This operation is the authenticated direct RPC endpoint and always uses the + POST `{payload: ...}` contract, including for functions whose DNS ingress is + configured in HTTP mode. + - The geo-routed DNS ingress is the function's `invoke_url`. It is on a + different domain from this API, so it cannot be derived from the API host. + - RPC-mode DNS ingress accepts POST at `/`. HTTP-mode DNS ingress accepts GET, + HEAD, POST, PUT, PATCH, and DELETE at `/` and nested paths. + - Direct and RPC-mode CORS preflight advertises `POST, OPTIONS`. HTTP-mode DNS + preflight advertises `GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`. + - `http_auth_mode: none` applies only to public HTTP-mode DNS ingress; this + direct operation always requires a Volcano credential. + + **Durable functions are not invocable here.** A durable function's id + answers 404, whatever its visibility, because a synchronous call would + run it with no execution record, no idempotency and no concurrency + accounting. Start one with + `POST /durable-functions/{functionId}/executions`. + operationId: invokeFunction security: - - UserToken: [] + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/FunctionId' requestBody: required: true content: - multipart/form-data: + application/json: schema: - type: object - properties: - functions: - type: string - description: | - JSON array of functions with `name`, `runtime`, optional `handler`, and `file_field`. Each `file_field` must name a multipart file field containing that function's ZIP or tar.gz source bundle. - - Each entry may also declare `variable_scope` (`all` or `scoped`) and `variables` (an array of project variable names). Omitting them leaves the function's stored declaration unchanged. Volcano detects direct environment references in the uploaded source code and keeps them separate from the declared names: detected names are not written back to the declaration and do not appear in a config export. A scoped function receives its declared names plus the detected ones the project defines; a detected name the project does not define is ignored, since such a reference is often optional. Detection reads code only, so a name appearing solely in a comment or in an unrelated string is not a reference. Declare a name when the function reads it through a computed key, or when it must not deploy without the variable. The request is rejected with 400 before anything is deployed if a scoped function declares a variable the project does not define, or if the resulting environment exceeds 4096 bytes. - code_0: - type: string - format: binary - description: Function ZIP or tar.gz archive referenced by the first manifest entry's `file_field`; additional code_N file fields may be included. Each archive is subject to SOURCE_ARCHIVE_SIZE_LIMIT_MB. - required: - - functions + $ref: '#/components/schemas/FunctionInvocationRequest' + examples: + serviceCall: + summary: Admin/background operation (service key) + value: + payload: + action: process_batch + items: + - 1 + - 2 + - 3 + userCall: + summary: User-initiated call (auth token) + value: + payload: + action: get_profile + anonCall: + summary: Public function call (anon key) + value: + payload: + action: ping_public_endpoint responses: - '202': - description: Batch deployment accepted - content: - application/json: + '200': + description: Function response (passthrough from function runtime) + headers: + X-Volcano-Version: + description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production) schema: - $ref: '#/components/schemas/BatchFunctionDeployResponse' - '207': - description: Batch deployment partially accepted; successful functions started deployment and failed functions were compensated where possible - content: - application/json: + type: string + X-Volcano-Region: + description: Region the function ran in (for example `us-east-1`) schema: - $ref: '#/components/schemas/BatchFunctionDeployResponse' - '400': - description: Bad request - content: - application/json: + type: string + X-Volcano-Proxy-Ms: + description: Milliseconds Volcano spent preparing the invocation, counted from the request arriving until the function was dispatched. Present only when the function was invoked. Does not include function execution. schema: - $ref: '#/components/schemas/Error' - '403': - description: Function limit exceeded for the project - content: - application/json: + type: integer + minimum: 0 + X-Volcano-Proxy-Handler-Ms: + description: The part of `X-Volcano-Proxy-Ms` spent in the invoke endpoint itself. Subtract it from `X-Volcano-Proxy-Ms` to see what authentication and request validation cost. Present only when the function was invoked. schema: - $ref: '#/components/schemas/Error' - '409': - description: | - A name in the batch is held by a function of the other kind — a - function cannot change kind — or the project's source is managed by - Git, where deploys come from a push to the production branch. + type: integer + minimum: 0 + X-Volcano-Compute-Ms: + description: Milliseconds spent running the function, from dispatch until it returned. Present only when the function was invoked. Does not include proxy preparation. + schema: + type: integer + minimum: 0 content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': - description: | - The batch carries a durable function and durable deploys are paused - platform-wide. The same request succeeds once they are re-enabled. + $ref: '#/components/schemas/FunctionInvocationResponse' + '400': + description: Bad request - invalid payload or function in failed state content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/schedulers: - get: - tags: - - Functions - summary: List every function scheduler in a project - description: | - Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`. - Returns schedulers across all functions in the project, ordered by - creation time descending, with standard page/limit pagination so - clients don't have to fan out one request per function. - operationId: listProjectSchedulers - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' - responses: - '200': - description: Project schedulers + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: - $ref: '#/components/schemas/FunctionSchedulerListResponse' - /projects/{id}/functions/{functionId}/schedulers: - get: - tags: - - Functions - summary: List schedulers for a function - operationId: listFunctionSchedulers - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' - responses: - '200': - description: Function schedulers + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - CORS blocked, missing `functions.invoke`, or private function with anon key content: application/json: schema: - $ref: '#/components/schemas/FunctionSchedulerListResponse' + $ref: '#/components/schemas/Error' '404': description: Function not found content: application/json: schema: $ref: '#/components/schemas/Error' - post: - tags: - - Functions - summary: Create a scheduler for a function - description: Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's deployed regions. - operationId: createFunctionScheduler - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateFunctionSchedulerRequest' - responses: - '201': - description: Scheduler created - content: - application/json: - schema: - $ref: '#/components/schemas/FunctionScheduler' - '400': + '429': description: | - Invalid schedule, geofenced region, a scheduler of this name - already exists on the function, or the function is not active. + Rate limit exceeded (per-function or project-wide limit), or the + owning platform user's billing-cycle bandwidth allowance (aggregate ingress + + egress) was exceeded. content: application/json: schema: $ref: '#/components/schemas/Error' - '403': + '503': description: | - Schedulers are not available on this plan, or the project already - holds as many as the plan allows. The cap counts standard and - durable function schedulers together. + Function still provisioning or rate limiting service unavailable. + A freshly deployed (or updated) function may briefly report + `provisioning` and reject invocations until the background status + reconciler observes its deployment workflow completing and transitions + it to `active`. This is expected for a few seconds after deploy; clients + should retry. content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Function not found + default: + description: Function response (passthrough; status code/body/headers come from the function) + headers: + X-Volcano-Version: + description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production) + schema: + type: string + X-Volcano-Region: + description: Region the function ran in (for example `us-east-1`) + schema: + type: string + X-Volcano-Proxy-Ms: + description: Milliseconds Volcano spent preparing the invocation, counted from the request arriving until the function was dispatched. Present only when the function was invoked. Does not include function execution. + schema: + type: integer + minimum: 0 + X-Volcano-Proxy-Handler-Ms: + description: The part of `X-Volcano-Proxy-Ms` spent in the invoke endpoint itself. Subtract it from `X-Volcano-Proxy-Ms` to see what authentication and request validation cost. Present only when the function was invoked. + schema: + type: integer + minimum: 0 + X-Volcano-Compute-Ms: + description: Milliseconds spent running the function, from dispatch until it returned. Present only when the function was invoked. Does not include proxy preparation. + schema: + type: integer + minimum: 0 content: application/json: schema: - $ref: '#/components/schemas/Error' - /projects/{id}/functions/{functionId}/schedulers/{schedulerId}: - get: - tags: - - Functions - summary: Get a function scheduler - operationId: getFunctionScheduler + $ref: '#/components/schemas/FunctionInvocationResponse' + /durable-functions/{functionId}/executions: + post: + tags: + - Durable Functions + summary: Start a durable execution from an application + description: | + Starts an execution of a durable function using an application + credential, and returns its handle. + + This is the durable counterpart of `POST /functions/{functionId}/invoke`, + and it is the endpoint an application calls. Like that one, it is not + project-scoped: an anon key, a service key and an auth user token each + carry their own project. The project-scoped collection under + `/projects/{id}/durable-functions/...` remains the owner's management + surface. + + **With a service key or an auth user token:** any durable function in + the project. + + **With an anon key:** requires the `functions.invoke` permission, and + the function must have `is_public: true`. + + Starting is all this endpoint does. Reading a result or stopping an + execution requires the project owner's token, because an anon key is + shared by everyone who loads the page and an execution is addressed by + id alone. + + Send `X-Volcano-Execution-Name` to make the start idempotent: repeating + a start with the same name returns the existing execution instead of + beginning a second one. + + Each execution counts once against the project's durable execution + allowance, however many times the start is retried under the same + execution name, and the number in flight at once is capped by the plan. + The operations the execution performs are counted against the durable + operations allowance when it finishes. + operationId: startDurableExecutionFromApplication security: - - UserToken: [] + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' - - $ref: '#/components/parameters/SchedulerId' + - $ref: '#/components/parameters/DurableFunctionId' + - name: X-Volcano-Execution-Name + in: header + required: false + description: | + Idempotency key for this execution. Generated when omitted. A repeat + under a name that already names a running execution returns that + execution and is not charged again. + + Letters, digits, `-`, `_` and `.`, up to 255 characters. Anything + else is rejected with `400`. + schema: + type: string + maxLength: 255 + pattern: ^[A-Za-z0-9._-]+$ + requestBody: + required: false + content: + application/json: + schema: + description: Input passed to the function, up to 256 KiB. responses: - '200': - description: Function scheduler + '202': + description: Execution accepted and started content: application/json: schema: - $ref: '#/components/schemas/FunctionScheduler' - '404': - description: Function or scheduler not found + $ref: '#/components/schemas/DurableExecution' + '400': + description: Payload is not valid JSON, or the execution name is invalid content: application/json: schema: $ref: '#/components/schemas/Error' - patch: - tags: - - Functions - summary: Update a function scheduler - operationId: updateFunctionScheduler - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' - - $ref: '#/components/parameters/SchedulerId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateFunctionSchedulerRequest' - responses: - '200': - description: Scheduler updated + '401': + description: | + Missing or invalid credential. Also returned for a platform user + token, which is not an application credential; project owners start + executions through the project-scoped collection. content: application/json: schema: - $ref: '#/components/schemas/FunctionScheduler' - '400': + $ref: '#/components/schemas/Error' + '403': description: | - Invalid schedule, geofenced region, or a scheduler of this name - already exists on the function. + The anon key lacks `functions.invoke`, the function is not public, + or the request's origin is refused by the project's CORS policy. content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Function or scheduler not found + description: | + Durable function not found. Also returned for a standard function's + id and for a durable function in another project, so the response + cannot be used to tell those apart. content: application/json: schema: $ref: '#/components/schemas/Error' - delete: - tags: - - Functions - summary: Delete a function scheduler - operationId: deleteFunctionScheduler - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' - - $ref: '#/components/parameters/SchedulerId' - responses: - '204': - description: Scheduler deleted - '404': - description: Function or scheduler not found + '409': + description: | + Function is not deployed yet, or has no deployed region. Also + returned when two starts under the same execution name raced and + both released it, which is retryable as it stands. content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/functions/{functionId}/deployments: - get: - tags: - - Functions - summary: List function deployments - operationId: listFunctionDeployments - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FunctionId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - responses: - '200': - description: Successful response + '413': + description: Payload is larger than 256 KiB content: application/json: schema: - $ref: '#/components/schemas/PaginatedFunctionDeployments' - '404': - description: Function not found + $ref: '#/components/schemas/Error' + '429': + description: | + The project has too many executions in flight for its plan, the + function invocation rate limit was exceeded, the project is over + its bandwidth cap, or the account is out of one of its + billing-cycle durable allowances: executions, operations, or + compute. Operations and compute are counted once an execution + finishes, so a refusal on either never interrupts an execution + already running — it declines the next start. content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions: + '503': + description: | + Durable execution is not available in this environment, or the + plan terms for the start could not be read. The first means the + capability is paused or this deployment cannot serve it, so it is + not one to retry in a loop; the second is transient. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /functions/resolve: get: tags: - - Durable Functions - summary: List all durable functions in a project + - Functions + summary: Resolve function name for invocation description: | - Standard functions never appear here, and durable functions never appear - under `/projects/{id}/functions`. The two are separate collections. - operationId: listDurableFunctions + Resolves a DNS-safe function name to its function ID and invocation URL within the caller's project. + + SDKs use this endpoint internally to invoke by function name while routing by function ID. + Invoke the returned `invoke_url` as-is. It does not share a domain with the API, so a host + built from the API URL will not reach the function. When the deployment serves no public + invocation domain, as in local development, `invoke_url` is omitted and callers invoke + through `POST /functions/{functionId}/invoke`. + + **With Service Key**: + - Allowed + + **With Auth User Token**: + - Allowed + + **With Anon Key**: + - Requires anon key permission: `functions.invoke` + - Function must have `is_public: true` + operationId: resolveFunctionForInvocation security: - - UserToken: [] + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Search' + - name: name + in: query + required: true + schema: + type: string + maxLength: 63 + pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ + description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) + example: my-function responses: '200': - description: Successful response + description: Function resolved successfully content: application/json: schema: - $ref: '#/components/schemas/PaginatedDurableFunctions' + $ref: '#/components/schemas/ResolveFunctionResponse' '400': - description: Bad request - invalid pagination parameters + description: Bad request - missing or invalid function name + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - CORS blocked or missing `functions.invoke` permission for anon key content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project not found + description: | + Function not found (or private function with anon key). A durable + function is never resolvable here: it is started through + `POST /durable-functions/{functionId}/executions`, not invoked. content: application/json: schema: $ref: '#/components/schemas/Error' + /projects/{id}/logs/activity: post: tags: - - Durable Functions - summary: Create or update a durable function + - Logs + summary: Get project log activity description: | - Upload a durable function source bundle. Creates the function on the - first call for a name and redeploys it on every call after that, the - same create-or-update contract `POST /projects/{id}/functions` has. - - Volcano builds and deploys asynchronously. A deployment that starts - immediately returns `status: provisioning`, then transitions to `active` - or `failed`; a deployment that has to wait for a running one is exposed - through `pending_deployment_id`. Existing executions keep running - against the runtime they started on. - - The `durable` configuration is derived from the project's plan rather - than supplied here, and is fixed once the function exists. A name - already held by a standard function is rejected with 409: a function - cannot change kind. - operationId: createDurableFunction + Retrieve bucketed log counts for one resource type in the project. Set + `resource.type` to `function`, `frontend`, or `database`. Add + `resource.ids` to filter to one or more resources, and add + `resource.deployments.ids` to count deployment logs instead of runtime + logs for functions and frontends. Deployment logs are not supported for + databases. Database logs are a SUPERAGENT feature; `resource.type=database` + from a HOBBY project owner returns 403. The activity window is limited + to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older start + times are clamped to that window. Buckets are aligned to UTC clock + intervals and count events in the half-open window + `[start_time, end_time)`. + operationId: getProjectLogActivity security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: - multipart/form-data: + application/json: schema: - type: object - required: - - name - - code - - runtime - properties: - name: - type: string - description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) - maxLength: 63 - pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ - example: order-pipeline - code: - type: string - format: binary - description: ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. - runtime: - type: string - enum: - - nodejs22.x - - nodejs24.x - - python3.13 - - python3.14 - description: | - Runtime environment. Required. Durable execution needs the - durable authoring API, which ships for these runtimes only; - any other runtime is rejected with 400 and the response - names the ones that work. Note that a durable Python - function needs a newer runtime than a standard one defaults - to. `GET /functions/runtimes` reports `durable_capable` per - runtime. - example: nodejs24.x - handler: - type: string - description: The name of the function to invoke. Defaults to "handler" if not specified. - default: handler - example: handler - is_public: - type: boolean - description: | - Whether anon keys with `functions.invoke` may start an - execution. Redeploying is the only way to change it, since - the collection has no update endpoint; omit it to keep the - current visibility, and a new function starts private. - - The standard collection's synchronous invocation fields — - `invocation_mode`, `http_auth_mode`, `openapi_spec` — - configure a request path no durable route serves, and are - rejected with 400 rather than ignored. - variable_scope: - type: string - enum: - - all - - scoped - description: | - Which project variables this function receives. `all` (the default) gives it every project variable; `scoped` gives it only the variables it selects. Omitting this leaves an existing function's scope unchanged. - variables: - type: string - description: | - JSON-encoded array of project variable names this function requires, on top of the ones detected in its source. A declared name the project does not define is rejected with 400; a detected name it does not define is ignored. Only used when `variable_scope` is `scoped`. Omitting this leaves an existing function's declared names unchanged. + $ref: '#/components/schemas/LogActivityRequest' responses: '200': - description: Existing durable function updated; its deployment was started or queued - content: - application/json: - schema: - $ref: '#/components/schemas/DurableFunction' - '201': - description: Durable function created and deployment workflow started + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DurableFunction' + $ref: '#/components/schemas/LogActivityResponse' '400': - description: | - Bad request (invalid archive, unsupported runtime, invalid name, or a - project region that does not offer durable execution — a durable - function deploys to every region of its project) - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Durable function limit exceeded for the project + description: Bad request - invalid query parameter content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Name is held by a standard function, or a deletion is queued or running + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal server error (function deployment failed) + '403': + description: Forbidden - project ownership required content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: | - Durable deploys are paused platform-wide. The same request succeeds - once they are re-enabled; executions already running are unaffected. + '404': + description: Project or resource not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions/{functionId}: - get: + /projects/{id}/logs/search: + post: tags: - - Durable Functions - summary: Get durable function by ID or name - operationId: getDurableFunction + - Logs + summary: Search project logs + description: | + Search or filter logs for one resource type in the project. Set + `resource.type` to `function`, `frontend`, or `database`. Add + `resource.ids` to filter to one or more resources, and add + `resource.deployments.ids` to read deployment logs instead of runtime + logs for functions and frontends. Deployment logs are not supported for + databases. Database logs are a SUPERAGENT feature; requests for + `resource.type=database` from a HOBBY project owner return 403. + Log history (runtime and deployment) is limited to the plan's retention + window (HOBBY: 1 day, SUPERAGENT: 30 days); older time ranges are clamped to that + window. + operationId: searchProjectLogs security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LogSearchRequest' responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DurableFunction' - '404': - description: Durable function not found + $ref: '#/components/schemas/LogSearchResponse' + '400': + description: Bad request - invalid query parameter content: application/json: schema: $ref: '#/components/schemas/Error' - delete: - tags: - - Durable Functions - summary: Delete a durable function - description: | - Accepted for asynchronous teardown; the work continues after the - response. The function's executions go with it: history stops being - readable whatever `retention_days` had left, and the executions still - running stop counting against the project's concurrency cap. Stop an - execution first if you need it to end before the function does. - operationId: deleteDurableFunction - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' - responses: - '202': - description: Deletion accepted and teardown started - '404': - description: | - Durable function not found. Also returned for an id that names a - durable function in another project, so the response cannot be used - to tell the two apart. + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions/{functionId}/deployments: - get: - tags: - - Durable Functions - summary: List durable function deployments - operationId: listDurableFunctionDeployments - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/PaginatedFunctionDeployments' - '404': - description: Durable function not found + '403': + description: Forbidden - project ownership required content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions/{functionId}/schedulers: - get: - tags: - - Durable Functions - summary: List schedulers for a durable function - description: | - The durable collection's counterpart to - `/projects/{id}/functions/{functionId}/schedulers`. A standard - function's id is not accepted here, and a durable function's id is not - accepted there. - operationId: listDurableFunctionSchedulers - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' - responses: - '200': - description: Durable function schedulers - content: - application/json: - schema: - $ref: '#/components/schemas/FunctionSchedulerListResponse' '404': - description: Durable function not found + description: Project or resource not found content: application/json: schema: $ref: '#/components/schemas/Error' + /projects/{id}/logs/stream: post: tags: - - Durable Functions - summary: Create a scheduler for a durable function + - Logs + summary: Stream project logs description: | - Each tick starts an execution rather than invoking the function, under - an execution name derived from the run, so a retried tick resolves to - the execution it already started. Requested regions must be a subset of - the function's deployed regions. + Live-tail project logs as Server-Sent Events. The request body uses the + resource selector plus `q`, `start_time`, and `limit`, + including runtime logs and function/frontend deployment logs selected + with `resource.deployments`. Deployment logs are not supported for + databases. Database logs are a SUPERAGENT feature; `resource.type=database` + from a HOBBY project owner returns 403. The `q` field uses the same + syntax as search and activity requests. Do not send `cursor` or + `end_time`; use `/logs/search` for range backfills. + Explicit historical `start_time` values are limited to the plan's + retention window (HOBBY: 1 day, SUPERAGENT: 30 days). Resume with + `Last-Event-ID` or the `last_event_id` query parameter. The cursor is + bound to the request body: the resource selector and every filter must + match the original request when reconnecting, otherwise the request is + rejected with `400`. - A tick draws on the same durable allowances and concurrency cap a - manual start does, and a tick that would exceed the cap fails that run. - operationId: createDurableFunctionScheduler + This is a live tail, not a gap-free backfill. On connect or reconnect the + server delivers at most `limit` of the most recent matching events from + the cursor position and then follows new events; events older than that + window are not replayed. Use `/logs/search` to backfill a time range. + operationId: streamProjectLogs security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' + - name: Last-Event-ID + in: header + required: false + schema: + type: string + description: Opaque stream cursor from the most recent SSE `id` field. + - name: last_event_id + in: query + required: false + schema: + type: string + description: Opaque stream cursor fallback when setting `Last-Event-ID` is not practical. requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/CreateFunctionSchedulerRequest' + $ref: '#/components/schemas/LogStreamRequest' responses: - '201': - description: Scheduler created - content: + '200': + description: Server-Sent Events stream. `log` events contain a JSON `LogSearchEvent`; `warning` events contain a JSON object with an `error` field. + content: + text/event-stream: + schema: + type: string + examples: + log: + summary: Log event + value: | + : connected + + id: STREAM_CURSOR + event: log + data: {"id":"LOG_EVENT_ID","timestamp":"2024-01-01T12:00:00Z","level":"info","message":"User logged in","resource":{"type":"function","id":"550e8400-e29b-41d4-a716-446655440000","name":"login"},"region":"us-east-1"} + '400': + description: Bad request - invalid selector, stream cursor, or unsupported stream field + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - project ownership required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Project or resource not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error - log streaming setup failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/functions/batch: + post: + tags: + - Functions + summary: Deploy multiple functions in one request + description: | + Upload multiple function source archives in one multipart request. Each archive should contain source files + plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads are + accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB` + for each uploaded and normalized source archive. The server records a shared + deployment batch ID for the resulting function deployments. Each function deployment runs its own + compile/publish workflow concurrently, and each publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` + for the final container image. + One batch request can include up to 100 functions. Submit multiple batch requests for larger projects. + If one function fails before its workflow starts, already-started function deployments are left + running and the failed function is reported in the `failed` array. Failed new functions are deleted; + failed updates are rolled back to their previous metadata/status where possible. + operationId: createFunctionsBatch + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + functions: + type: string + description: | + JSON array of functions with `name`, `runtime`, optional `handler`, and `file_field`. Each `file_field` must name a multipart file field containing that function's ZIP or tar.gz source bundle. + + Each entry may also declare `variable_scope` (`all` or `scoped`) and `variables` (an array of project variable names). Omitting them leaves the function's stored declaration unchanged. Volcano detects direct environment references in the uploaded source code and keeps them separate from the declared names: detected names are not written back to the declaration and do not appear in a config export. A scoped function receives its declared names plus the detected ones the project defines; a detected name the project does not define is ignored, since such a reference is often optional. Detection reads code only, so a name appearing solely in a comment or in an unrelated string is not a reference. Declare a name when the function reads it through a computed key, or when it must not deploy without the variable. The request is rejected with 400 before anything is deployed if a scoped function declares a variable the project does not define, or if the resulting environment exceeds 4096 bytes. + code_0: + type: string + format: binary + description: Function ZIP or tar.gz archive referenced by the first manifest entry's `file_field`; additional code_N file fields may be included. Each archive is subject to SOURCE_ARCHIVE_SIZE_LIMIT_MB. + required: + - functions + responses: + '202': + description: Batch deployment accepted + content: + application/json: + schema: + $ref: '#/components/schemas/BatchFunctionDeployResponse' + '207': + description: Batch deployment partially accepted; successful functions started deployment and failed functions were compensated where possible + content: + application/json: + schema: + $ref: '#/components/schemas/BatchFunctionDeployResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Function limit exceeded for the project + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: | + A name in the batch is held by a function of the other kind — a + function cannot change kind — or the project's source is managed by + Git, where deploys come from a push to the production branch. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: | + The owner's billing-cycle build-minutes allowance is spent. The + error names the allowance and carries a link to the usage page. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: | + Build usage could not be read, so the allowance could not be + checked. The same request succeeds once it can be. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/schedulers: + get: + tags: + - Functions + summary: List every function scheduler in a project + description: | + Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`. + Returns schedulers across all functions in the project, ordered by + creation time descending, with standard page/limit pagination so + clients don't have to fan out one request per function. + operationId: listProjectSchedulers + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + responses: + '200': + description: Project schedulers + content: + application/json: + schema: + $ref: '#/components/schemas/FunctionSchedulerListResponse' + /projects/{id}/functions/{functionId}/schedulers: + get: + tags: + - Functions + summary: List schedulers for a function + operationId: listFunctionSchedulers + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/FunctionId' + responses: + '200': + description: Function schedulers + content: + application/json: + schema: + $ref: '#/components/schemas/FunctionSchedulerListResponse' + '404': + description: Function not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + tags: + - Functions + summary: Create a scheduler for a function + description: Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's deployed regions. + operationId: createFunctionScheduler + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/FunctionId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateFunctionSchedulerRequest' + responses: + '201': + description: Scheduler created + content: application/json: schema: $ref: '#/components/schemas/FunctionScheduler' @@ -4068,46 +4504,48 @@ paths: schema: $ref: '#/components/schemas/Error' '404': - description: Durable function not found + description: Function not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions/{functionId}/schedulers/{schedulerId}: + /projects/{id}/functions/{functionId}/schedulers/{schedulerId}: get: tags: - - Durable Functions - summary: Get a durable function scheduler - operationId: getDurableFunctionScheduler + - Functions + summary: Get a function scheduler + operationId: getFunctionScheduler security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/FunctionId' - $ref: '#/components/parameters/SchedulerId' responses: '200': - description: Durable function scheduler + description: Function scheduler content: application/json: schema: $ref: '#/components/schemas/FunctionScheduler' '404': - description: Durable function or scheduler not found + description: Function or scheduler not found content: application/json: schema: $ref: '#/components/schemas/Error' patch: tags: - - Durable Functions - summary: Update a durable function scheduler - operationId: updateDurableFunctionScheduler + - Functions + summary: Update a function scheduler + operationId: updateFunctionScheduler security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/FunctionId' - $ref: '#/components/parameters/SchedulerId' requestBody: required: true @@ -4131,757 +4569,802 @@ paths: schema: $ref: '#/components/schemas/Error' '404': - description: Durable function or scheduler not found + description: Function or scheduler not found content: application/json: schema: $ref: '#/components/schemas/Error' delete: tags: - - Durable Functions - summary: Delete a durable function scheduler - operationId: deleteDurableFunctionScheduler + - Functions + summary: Delete a function scheduler + operationId: deleteFunctionScheduler security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/FunctionId' - $ref: '#/components/parameters/SchedulerId' responses: '204': description: Scheduler deleted '404': - description: Durable function or scheduler not found + description: Function or scheduler not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions/{functionId}/executions: - post: + /projects/{id}/functions/{functionId}/deployments: + get: tags: - - Durable Functions - summary: Start a durable execution - description: | - Starts an execution and returns its handle. Never returns a result: an - execution can outlive any request a client could hold open, so the - result is read back from - `GET /projects/{id}/durable-functions/{functionId}/executions/{executionId}`. - - The request body is the execution's input and must be valid JSON if - present. An empty body starts the execution with no input. - - Send `X-Volcano-Execution-Name` to make the start idempotent: repeating a - start with the same name returns the existing execution instead of - beginning a second one. - - Each execution counts against the project's durable execution - allowance, the operations it performs count against the durable - operations allowance when it finishes, and the number of executions in - flight at once is capped by the plan. - operationId: startDurableExecution + - Functions + summary: List function deployments + operationId: listFunctionDeployments security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' - - name: X-Volcano-Execution-Name - in: header - required: false - description: | - Idempotency key for this execution. Generated when omitted. A repeat - under a name that already names a running execution returns that - execution and is not charged again. - - Letters, digits, `-`, `_` and `.`, up to 255 characters. Anything - else is rejected with `400`. - schema: - type: string - maxLength: 255 - pattern: ^[A-Za-z0-9._-]+$ - requestBody: - required: false - content: - application/json: - schema: - description: Input passed to the function, up to 256 KiB. + - $ref: '#/components/parameters/FunctionId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' responses: - '202': - description: Execution accepted and started - content: - application/json: - schema: - $ref: '#/components/schemas/DurableExecution' - '400': - description: Payload is not valid JSON, or the execution name is invalid + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/PaginatedFunctionDeployments' '404': - description: Durable function not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: | - Function is not deployed yet, or has no deployed region. Also - returned when two starts under the same execution name raced and - both released it, which is retryable as it stands. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '413': - description: Payload exceeds the maximum execution input size - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '429': - description: | - Too many executions already in flight for this project, or the - account is out of one of its billing-cycle durable allowances: - executions, operations, or compute. An owner-started execution is - metered exactly like an application-started one. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '503': - description: | - Durable execution is not available in this environment, or the - usage limit service could not be reached to charge the start. The - first is returned by a deployment that has no durable execution - engine, such as a local one, and is not retryable there; the second - is transient. + description: Function not found content: application/json: schema: $ref: '#/components/schemas/Error' + /projects/{id}/durable-functions: get: tags: - Durable Functions - summary: List a durable function's executions + summary: List all durable functions in a project description: | - Returns the platform's last observed status for each execution; listing - does not poll each one. Fetch a single execution for its live state. - operationId: listDurableExecutions + Standard functions never appear here, and durable functions never appear + under `/projects/{id}/functions`. The two are separate collections. + operationId: listDurableFunctions security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/Limit' - - name: status - in: query - required: false - description: Return only executions in this status. - schema: - $ref: '#/components/schemas/DurableExecutionStatus' + - $ref: '#/components/parameters/Search' responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/PaginatedDurableExecutions' + $ref: '#/components/schemas/PaginatedDurableFunctions' '400': - description: Unsupported status filter + description: Bad request - invalid pagination parameters content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Durable function not found + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions/{functionId}/executions/{executionId}: - get: + post: tags: - Durable Functions - summary: Get a durable execution + summary: Create or update a durable function description: | - Returns the execution's current state, including its `result` once it has - succeeded. Poll this to wait for an execution to finish. - operationId: getDurableExecution + Upload a durable function source bundle. Creates the function on the + first call for a name and redeploys it on every call after that, the + same create-or-update contract `POST /projects/{id}/functions` has. + + Volcano builds and deploys asynchronously. A deployment that starts + immediately returns `status: provisioning`, then transitions to `active` + or `failed`; a deployment that has to wait for a running one is exposed + through `pending_deployment_id`. Existing executions keep running + against the runtime they started on. + + The `durable` configuration is derived from the project's plan rather + than supplied here, and is fixed once the function exists. A name + already held by a standard function is rejected with 409: a function + cannot change kind. + operationId: createDurableFunction security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' - - $ref: '#/components/parameters/DurableExecutionId' + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: + - name + - code + - runtime + properties: + name: + type: string + description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen) + maxLength: 63 + pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ + example: order-pipeline + code: + type: string + format: binary + description: ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. + runtime: + type: string + enum: + - nodejs22.x + - nodejs24.x + - python3.13 + - python3.14 + description: | + Runtime environment. Required. Durable execution needs the + durable authoring API, which ships for these runtimes only; + any other runtime is rejected with 400 and the response + names the ones that work. Note that a durable Python + function needs a newer runtime than a standard one defaults + to. `GET /functions/runtimes` reports `durable_capable` per + runtime. + example: nodejs24.x + handler: + type: string + description: The name of the function to invoke. Defaults to "handler" if not specified. + default: handler + example: handler + is_public: + type: boolean + description: | + Whether anon keys with `functions.invoke` may start an + execution. Redeploying is the only way to change it, since + the collection has no update endpoint; omit it to keep the + current visibility, and a new function starts private. + + The standard collection's synchronous invocation fields — + `invocation_mode`, `http_auth_mode`, `openapi_spec` — + configure a request path no durable route serves, and are + rejected with 400 rather than ignored. + variable_scope: + type: string + enum: + - all + - scoped + x-enum-varnames: + - CreateDurableFunctionMultipartBodyVariableScopeAll + - CreateDurableFunctionMultipartBodyVariableScopeScoped + description: | + Which project variables this function receives. `all` (the default) gives it every project variable; `scoped` gives it only the variables it selects. Omitting this leaves an existing function's scope unchanged. + variables: + type: string + description: | + JSON-encoded array of project variable names this function requires, on top of the ones detected in its source. A declared name the project does not define is rejected with 400; a detected name it does not define is ignored. Only used when `variable_scope` is `scoped`. Omitting this leaves an existing function's declared names unchanged. responses: '200': - description: Successful response + description: Existing durable function updated; its deployment was started or queued content: application/json: schema: - $ref: '#/components/schemas/DurableExecution' - '404': - description: Durable function or execution not found + $ref: '#/components/schemas/DurableFunction' + '201': + description: Durable function created and deployment workflow started content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': + $ref: '#/components/schemas/DurableFunction' + '400': description: | - Durable execution is not available in this environment. Returned by - a deployment that has no durable execution engine, such as a local - one; the request is not retryable there. + Bad request (invalid archive, unsupported runtime, invalid name, or a + project region that does not offer durable execution — a durable + function deploys to every region of its project) content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/durable-functions/{functionId}/executions/{executionId}/stop: - post: - tags: - - Durable Functions - summary: Stop a durable execution - description: | - Cancels a running execution. Its completed steps are not undone. - - The call is accepted rather than awaited: cancellation happens behind - it, so the response reports the execution as it was read back and may - still say `running`. Do not branch on that status — the execution - settles into `stopped` shortly after, and polling - `GET /projects/{id}/durable-functions/{functionId}/executions/{executionId}` - is how you see it get there. - - Stopping an execution that already finished is not an error: the - response carries the state it settled in. - operationId: stopDurableExecution - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DurableFunctionId' - - $ref: '#/components/parameters/DurableExecutionId' - responses: - '200': - description: | - Stop accepted. The body is the execution as it was read back, which - may still report `running`. + '403': + description: Durable function limit exceeded for the project content: application/json: schema: - $ref: '#/components/schemas/DurableExecution' - '404': - description: Durable function or execution not found + $ref: '#/components/schemas/Error' + '409': + description: Name is held by a standard function, or a deletion is queued or running content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Execution has not started yet + '500': + description: Internal server error (function deployment failed) content: application/json: schema: $ref: '#/components/schemas/Error' '503': description: | - Durable execution is not available in this environment. Returned by - a deployment that has no durable execution engine, such as a local - one; the request is not retryable there. + Durable deploys are paused platform-wide. The same request succeeds + once they are re-enabled; executions already running are unaffected. content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/frontends: + /projects/{id}/durable-functions/{functionId}: get: tags: - - Frontends - summary: List all frontends in a project - description: | - Supports two mutually exclusive pagination modes. Offset mode uses `page` - and `limit` and returns `next` (URL). Cursor mode uses `cursor` and - `limit`, supports `search` (case-insensitive name match), and returns - `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`) - returns 400. - operationId: listFrontends + - Durable Functions + summary: Get durable function by ID or name + operationId: getDurableFunction security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' + - $ref: '#/components/parameters/DurableFunctionId' responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/PaginatedFrontends' - '400': - description: Bad request - invalid project identifier + $ref: '#/components/schemas/DurableFunction' + '404': + description: Durable function not found content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + delete: + tags: + - Durable Functions + summary: Delete a durable function + description: | + Accepted for asynchronous teardown; the work continues after the + response. The function's executions go with it: executions still in + flight are stopped, and history stops being readable whatever + `retention_days` had left. + + Stopping is asynchronous at the platform, and it does not interrupt a + step already running -- that step runs to its next checkpoint. So a + delete ends an execution rather than halting it mid-step; stop the + execution yourself first if you need to observe it ending. + operationId: deleteDurableFunction + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DurableFunctionId' + responses: + '202': + description: Deletion accepted and teardown started + '404': + description: | + Durable function not found. Also returned for an id that names a + durable function in another project, so the response cannot be used + to tell the two apart. content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required + /projects/{id}/durable-functions/{functionId}/deployments: + get: + tags: + - Durable Functions + summary: List durable function deployments + operationId: listDurableFunctionDeployments + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + responses: + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/PaginatedFunctionDeployments' '404': - description: Project not found + description: Durable function not found content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal server error + /projects/{id}/durable-functions/{functionId}/schedulers: + get: + tags: + - Durable Functions + summary: List schedulers for a durable function + description: | + The durable collection's counterpart to + `/projects/{id}/functions/{functionId}/schedulers`. A standard + function's id is not accepted here, and a durable function's id is not + accepted there. + operationId: listDurableFunctionSchedulers + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DurableFunctionId' + responses: + '200': + description: Durable function schedulers + content: + application/json: + schema: + $ref: '#/components/schemas/FunctionSchedulerListResponse' + '404': + description: Durable function not found content: application/json: schema: $ref: '#/components/schemas/Error' post: tags: - - Frontends - summary: Create a new frontend deployment + - Durable Functions + summary: Create a scheduler for a durable function description: | - Creates and deploys a frontend for the project. - If a frontend with the same name already exists in the project, this operation updates that - frontend using the uploaded archive and starts a new deployment. A deployment that starts - immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or - `failed`. If another deployment is running, the response preserves the frontend's current status - and exposes the queued deployment through `pending_deployment_id`. - Existing frontend traffic continues to use an available runtime while the new deployment builds - and provisions. Each deployment publishes its own static assets before the runtimes switch to its - build, and the live build's assets keep serving until the new deployment is live, so a page loaded - mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes - back on the build they were running, leaves the frontend `active` on the previous deployment, and - records the attempted deployment as failed. `degraded` means the runtime remains available but - edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a - given frontend, while independent frontends and projects can deploy concurrently. - For monorepos, provide `app_root` as a relative path from the uploaded archive root - to the Next.js app that should be built. Omit it for single-app archives. - Supported frontend environments are Next.js 15.x and 16.x with Node.js - 22.x or 24.x. The Node.js runtime is inferred from - `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x. - The selected Node.js family must also satisfy the installed Next.js package's - `engines.node` constraint. Volcano tests Next 15.5.25 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.5 (`>=20.9.0`). - Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI - does not apply its own source archive size limit. After the final container images are - built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. - This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`). - Each project can contain up to 10,000 frontends regardless of plan. - operationId: createFrontend + Each tick starts an execution rather than invoking the function, under + an execution name derived from the run, so a retried tick resolves to + the execution it already started. Requested regions must be a subset of + the function's deployed regions. + + A tick draws on the same durable allowances and concurrency cap a + manual start does, and a tick that would exceed the cap fails that run. + operationId: createDurableFunctionScheduler security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DurableFunctionId' requestBody: required: true content: - multipart/form-data: + application/json: schema: - type: object - required: - - name - - archive - properties: - name: - type: string - maxLength: 63 - pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ - description: DNS-safe frontend name - framework: - type: string - enum: - - nextjs - default: nextjs - description: Next.js frontend. Supported Next.js majors are 15.x and 16.x. - app_root: - type: string - maxLength: 1024 - description: Optional relative POSIX path from the uploaded archive root to the Next.js app to build, for example `apps/web`. - example: apps/web - archive: - type: string - format: binary - description: ZIP or tar.gz archive of the frontend project directory or monorepo workspace root. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz archive. + $ref: '#/components/schemas/CreateFunctionSchedulerRequest' responses: - '200': - description: Existing frontend updated; its deployment was started or queued - content: - application/json: - schema: - $ref: '#/components/schemas/Frontend' '201': - description: Frontend created and deployment workflow started + description: Scheduler created content: application/json: schema: - $ref: '#/components/schemas/Frontend' + $ref: '#/components/schemas/FunctionScheduler' '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + description: | + Invalid schedule, geofenced region, a scheduler of this name + already exists on the function, or the function is not active. content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Frontend deployment limit exceeded for the current plan or project hard cap + description: | + Schedulers are not available on this plan, or the project already + holds as many as the plan allows. The cap counts standard and + durable function schedulers together. content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: Conflict - frontend deletion is queued or running + description: Durable function not found content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal server error + /projects/{id}/durable-functions/{functionId}/schedulers/{schedulerId}: + get: + tags: + - Durable Functions + summary: Get a durable function scheduler + operationId: getDurableFunctionScheduler + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/SchedulerId' + responses: + '200': + description: Durable function scheduler content: application/json: schema: - $ref: '#/components/schemas/Error' - '503': - description: Service unavailable - frontend workflow or archive limit configuration missing + $ref: '#/components/schemas/FunctionScheduler' + '404': + description: Durable function or scheduler not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/frontends/{frontendId}: - get: + patch: tags: - - Frontends - summary: Get frontend details - operationId: getFrontend + - Durable Functions + summary: Update a durable function scheduler + operationId: updateDurableFunctionScheduler security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FrontendId' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/SchedulerId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateFunctionSchedulerRequest' responses: '200': - description: Successful response + description: Scheduler updated content: application/json: schema: - $ref: '#/components/schemas/Frontend' + $ref: '#/components/schemas/FunctionScheduler' '400': - description: Bad request - invalid identifier - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + description: | + Invalid schedule, geofenced region, or a scheduler of this name + already exists on the function. content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Frontend not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error + '404': + description: Durable function or scheduler not found content: application/json: schema: $ref: '#/components/schemas/Error' delete: tags: - - Frontends - summary: Delete a frontend - description: | - Schedules asynchronous frontend deletion. If another deployment is running, the frontend - preserves its current status and exposes the queued deletion through `pending_deployment_id`. - Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no - longer appears in frontend lists. - operationId: deleteFrontend + - Durable Functions + summary: Delete a durable function scheduler + operationId: deleteDurableFunctionScheduler security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FrontendId' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/SchedulerId' responses: - '202': - description: Frontend deletion started or queued - '400': - description: Bad request - invalid identifier - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '204': + description: Scheduler deleted '404': - description: Frontend not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '503': - description: Service unavailable - frontend workflow configuration missing + description: Durable function or scheduler not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/frontends/{frontendId}/redeploy: + /projects/{id}/durable-functions/{functionId}/executions: post: tags: - - Frontends - summary: Redeploy frontend using latest uploaded artifact + - Durable Functions + summary: Start a durable execution description: | - Starts a new frontend workflow using the latest stored artifact. A deployment that starts - immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or - `failed`. An overlapping deployment preserves the frontend's current status, is exposed through - `pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its - published static assets remain available during provisioning, and a failed redeploy restores the - regional runtimes to that build and keeps it serving while the attempted deployment is recorded as - failed. - operationId: redeployFrontend + Starts an execution and returns its handle. Never returns a result: an + execution can outlive any request a client could hold open, so the + result is read back from + `GET /projects/{id}/durable-functions/{functionId}/executions/{executionId}`. + + The request body is the execution's input and must be valid JSON if + present. An empty body starts the execution with no input. + + Send `X-Volcano-Execution-Name` to make the start idempotent: repeating a + start with the same name returns the existing execution instead of + beginning a second one. + + Each execution counts against the project's durable execution + allowance, the operations it performs count against the durable + operations allowance when it finishes, and the number of executions in + flight at once is capped by the plan. + operationId: startDurableExecution security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FrontendId' + - $ref: '#/components/parameters/DurableFunctionId' + - name: X-Volcano-Execution-Name + in: header + required: false + description: | + Idempotency key for this execution. Generated when omitted. A repeat + under a name that already names a running execution returns that + execution and is not charged again. + + Letters, digits, `-`, `_` and `.`, up to 255 characters. Anything + else is rejected with `400`. + schema: + type: string + maxLength: 255 + pattern: ^[A-Za-z0-9._-]+$ + requestBody: + required: false + content: + application/json: + schema: + description: Input passed to the function, up to 256 KiB. responses: - '200': - description: Frontend redeploy started or queued + '202': + description: Execution accepted and started content: application/json: schema: - $ref: '#/components/schemas/Frontend' + $ref: '#/components/schemas/DurableExecution' '400': - description: Bad request - invalid identifier - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + description: Payload is not valid JSON, or the execution name is invalid content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required + '404': + description: Durable function not found content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Frontend not found + '409': + description: | + Function is not deployed yet, or has no deployed region. Also + returned when two starts under the same execution name raced and + both released it, which is retryable as it stands. content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Conflict - frontend deletion is queued or running + '413': + description: Payload exceeds the maximum execution input size content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal server error + '429': + description: | + Too many executions already in flight for this project, or the + account is out of one of its billing-cycle durable allowances: + executions, operations, or compute. An owner-started execution is + metered exactly like an application-started one. content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Service unavailable - frontend workflow configuration missing + description: | + Durable execution is not available in this environment, or the + plan terms for the start could not be read. The first means the + capability is paused or this deployment cannot serve it, so it is + not one to retry in a loop; the second is transient. content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/frontends/{frontendId}/domain: get: tags: - - Frontends - summary: Get frontend custom domain status - operationId: getFrontendCustomDomain + - Durable Functions + summary: List a durable function's executions + description: | + Returns the platform's last observed status for each execution; listing + does not poll each one. Fetch a single execution for its live state. + operationId: listDurableExecutions security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FrontendId' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - name: status + in: query + required: false + description: Return only executions in this status. + schema: + $ref: '#/components/schemas/DurableExecutionStatus' responses: '200': - description: | - Frontend custom domain status, or null when the frontend has no - custom domain configured (the common empty state). + description: Successful response content: application/json: schema: - nullable: true - allOf: - - $ref: '#/components/schemas/FrontendCustomDomainResponse' + $ref: '#/components/schemas/PaginatedDurableExecutions' '400': - description: Bad request - invalid identifier + description: Unsupported status filter content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + '404': + description: Durable function not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - project ownership required + /projects/{id}/durable-functions/{functionId}/executions/{executionId}: + get: + tags: + - Durable Functions + summary: Get a durable execution + description: | + Returns the execution's current state, including its `result` once it has + succeeded. Poll this to wait for an execution to finish. + operationId: getDurableExecution + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/DurableExecutionId' + responses: + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/DurableExecution' '404': - description: Frontend not found + description: Durable function or execution not found content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal server error + '503': + description: | + Durable execution is not available in this environment. Either the + capability is paused or this deployment cannot serve it, so the + request is not one to retry in a loop. content: application/json: schema: $ref: '#/components/schemas/Error' - post: + /projects/{id}/durable-functions/{functionId}/executions/{executionId}/operations: + get: tags: - - Frontends - summary: Configure frontend custom domain (SUPERAGENT) + - Durable Functions + summary: List a durable execution's operations description: | - Configures one custom domain for a frontend. - The default Volcano-generated frontend URL remains active. - Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes. - operationId: createFrontendCustomDomain + Returns the execution's trace: every operation it began — each step, + wait, poll, child context, map item and parallel branch — with when it + started and ended, how it ended, and each attempt of a retried step. + `invocations` are the windows the function's code was actually running; + the gaps between them are time the execution spent suspended, which is + not charged. + + A finished execution's trace is final and `complete` is `true`. A + running one is refreshed when it is read, and can be up to about ten + seconds behind; `synced_at` says when it was last refreshed. Inputs, + results and other payloads are never included. + + The list is not paginated: an execution is limited to 3,000 + operations, and a trace is read whole. + operationId: listDurableExecutionOperations security: - UserToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FrontendId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateFrontendCustomDomainRequest' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/DurableExecutionId' responses: '200': - description: Custom domain already configured with same hostname - content: - application/json: - schema: - $ref: '#/components/schemas/FrontendCustomDomainResponse' - '201': - description: Custom domain provisioning started + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/FrontendCustomDomainResponse' - '400': - description: Bad request - invalid domain + $ref: '#/components/schemas/DurableExecutionOperationList' + '404': + description: Durable function or execution not found content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - invalid or missing token + '500': + description: The trace could not be read content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Forbidden - custom domains require SUPERAGENT plan + '503': + description: | + Durable execution is not available in this environment. Either the + capability is paused or this deployment cannot serve it, so the + request is not one to retry in a loop. content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Frontend not found + /projects/{id}/durable-functions/{functionId}/executions/{executionId}/stop: + post: + tags: + - Durable Functions + summary: Stop a durable execution + description: | + Cancels a running execution. Its completed steps are not undone. + + The call is accepted rather than awaited: cancellation happens behind + it, so the response reports the execution as it was read back and may + still say `running`. Do not branch on that status — the execution + settles into `stopped` shortly after, and polling + `GET /projects/{id}/durable-functions/{functionId}/executions/{executionId}` + is how you see it get there. + + Stopping an execution that already finished is not an error: the + response carries the state it settled in. + operationId: stopDurableExecution + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DurableFunctionId' + - $ref: '#/components/parameters/DurableExecutionId' + responses: + '200': + description: | + Stop accepted. The body is the execution as it was read back, which + may still report `running`. content: application/json: schema: - $ref: '#/components/schemas/Error' - '409': - description: Conflict - custom domain already in use, still detaching, or frontend already has a custom domain + $ref: '#/components/schemas/DurableExecution' + '404': + description: Durable function or execution not found content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Internal server error + '409': + description: Execution has not started yet content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Service unavailable - custom domain provisioning is temporarily unavailable + description: | + Durable execution is not available in this environment. Either the + capability is paused or this deployment cannot serve it, so the + request is not one to retry in a loop. content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /projects/{id}/frontends: + get: tags: - Frontends - summary: Delete frontend custom domain - operationId: deleteFrontendCustomDomain + summary: List all frontends in a project + description: | + Supports two mutually exclusive pagination modes. Offset mode uses `page` + and `limit` and returns `next` (URL). Cursor mode uses `cursor` and + `limit`, supports `search` (case-insensitive name match), and returns + `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`) + returns 400. + operationId: listFrontends security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FrontendId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' responses: - '204': - description: Custom domain detach scheduled + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedFrontends' '400': - description: Bad request - invalid identifier + description: Bad request - invalid project identifier content: application/json: schema: @@ -4899,7 +5382,7 @@ paths: schema: $ref: '#/components/schemas/Error' '404': - description: Frontend or custom domain not found + description: Project not found content: application/json: schema: @@ -4910,28 +5393,100 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/frontends/{frontendId}/deployments: - get: + post: tags: - Frontends - summary: List frontend deployments - operationId: listFrontendDeployments + summary: Create a new frontend deployment + description: | + Creates and deploys a frontend for the project. + If a frontend with the same name already exists in the project, this operation updates that + frontend using the uploaded archive and starts a new deployment. A deployment that starts + immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or + `failed`. If another deployment is running, the response preserves the frontend's current status + and exposes the queued deployment through `pending_deployment_id`. + Existing frontend traffic continues to use an available runtime while the new deployment builds + and provisions. Each deployment publishes its own static assets before the runtimes switch to its + build, and the live build's assets keep serving until the new deployment is live, so a page loaded + mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes + back on the build they were running, leaves the frontend `active` on the previous deployment, and + records the attempted deployment as failed. `degraded` means the runtime remains available but + edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a + given frontend, while independent frontends and projects can deploy concurrently. + For monorepos, provide `app_root` as a relative path from the uploaded archive root + to the Next.js app that should be built. Omit it for single-app archives. + Supported frontend environments are Next.js 15.x and 16.x with Node.js + 22.x or 24.x. The Node.js runtime is inferred from + `package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x. + The selected Node.js family must also satisfy the installed Next.js package's + `engines.node` constraint. Volcano tests Next 15.5.26 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.6 (`>=20.9.0`). + Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI + does not apply its own source archive size limit. After the final container images are + built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing. + This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`). + Each project can contain up to 10,000 frontends regardless of plan. + operationId: createFrontend security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/FrontendId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: + - name + - archive + properties: + name: + type: string + maxLength: 63 + pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ + description: DNS-safe frontend name + framework: + type: string + enum: + - nextjs + default: nextjs + description: Next.js frontend. Supported Next.js majors are 15.x and 16.x. + app_root: + type: string + maxLength: 1024 + description: Optional relative POSIX path from the uploaded archive root to the Next.js app to build, for example `apps/web`. + example: apps/web + variable_scope: + type: string + enum: + - all + - scoped + description: Variable selection for this deployment. New frontends default to `scoped`; omitting this field for an existing frontend preserves its current selection. + variables: + type: array + items: + type: string + pattern: ^[A-Za-z_][A-Za-z0-9_]*$ + description: Project variable names selected when `variable_scope` is `scoped`. Submit each name as a repeated multipart field. + archive: + type: string + format: binary + description: ZIP or tar.gz archive of the frontend project directory or monorepo workspace root. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz archive. responses: '200': - description: Successful response + description: Existing frontend updated; its deployment was started or queued content: application/json: schema: - $ref: '#/components/schemas/PaginatedFrontendDeployments' + $ref: '#/components/schemas/Frontend' + '201': + description: Frontend created and deployment workflow started + content: + application/json: + schema: + $ref: '#/components/schemas/Frontend' '400': - description: Bad request - invalid identifier + description: Bad request content: application/json: schema: @@ -4943,13 +5498,19 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: Forbidden - project ownership required + description: Frontend deployment limit exceeded for the current plan or project hard cap content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Frontend not found + description: Project not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: Conflict - frontend deletion is queued or running content: application/json: schema: @@ -4960,43 +5521,31 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/frontends/{frontendId}/usage: + '503': + description: Service unavailable - frontend workflow or archive limit configuration missing + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/frontends/{frontendId}: get: tags: - Frontends - summary: Per-day request and error counts for a single frontend - description: | - Returns a zero-filled daily series of request counts and 5xx - error counts for one frontend, oldest first. Each entry is one - UTC day; missing days (no traffic recorded) come back as - `requests: 0, errors: 0` so the response always has exactly - `days` entries. - - Backs the Monitoring section on the Frontend detail page in - volcano-web. `days` defaults to 30 and is capped at 90 to keep - the (frontend_id, day) index scan bounded. - operationId: getFrontendUsageHistory + summary: Get frontend details + operationId: getFrontend security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/FrontendId' - - name: days - in: query - description: Number of trailing days to return (1–90, default 30). - required: false - schema: - type: integer - minimum: 1 - maximum: 90 - default: 30 responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/FrontendUsageHistoryResponse' + $ref: '#/components/schemas/Frontend' '400': description: Bad request - invalid identifier content: @@ -5027,2654 +5576,2508 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/variables: - get: + delete: tags: - - Variables - summary: List all variables for a project + - Frontends + summary: Delete a frontend description: | - Returns project-level environment variables used by deployed functions and frontends. - operationId: listVariables + Schedules asynchronous frontend deletion. If another deployment is running, the frontend + preserves its current status and exposes the queued deletion through `pending_deployment_id`. + Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no + longer appears in frontend lists. + operationId: deleteFrontend security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' + - $ref: '#/components/parameters/FrontendId' responses: - '200': - description: Successful response + '202': + description: Frontend deletion started or queued + '400': + description: Bad request - invalid identifier content: application/json: schema: - $ref: '#/components/schemas/PaginatedVariables' + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - project ownership required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Project not found + description: Frontend not found content: application/json: schema: $ref: '#/components/schemas/Error' - post: - tags: - - Variables - summary: Create or update a variable - description: | - Creates a project-level environment variable and triggers asynchronous propagation - to deployed functions and frontends in the project's configured regions. - operationId: createVariable - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateVariableRequest' - responses: - '201': - description: Variable created - content: - application/json: - schema: - $ref: '#/components/schemas/Variable' - '400': - description: Bad request + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Private variable membership writes are disabled during rollout + description: Service unavailable - frontend workflow configuration missing content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases: - get: + /projects/{id}/frontends/{frontendId}/redeploy: + post: tags: - - Databases - summary: List all databases for a project + - Frontends + summary: Redeploy frontend using latest uploaded artifact description: | - Supports two mutually exclusive pagination modes. Offset mode uses `page` - and `limit`. Cursor mode uses `cursor` and `limit`, supports `search` - (case-insensitive name match), and returns `next_cursor`/`prev_cursor`. - The optional `status` filter applies in both modes and is bound to the - cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400. - operationId: listDatabases + Starts a new frontend workflow using the latest stored artifact. A deployment that starts + immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or + `failed`. An overlapping deployment preserves the frontend's current status, is exposed through + `pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its + published static assets remain available during provisioning, and a failed redeploy restores the + regional runtimes to that build and keeps it serving while the attempted deployment is recorded as + failed. + operationId: redeployFrontend security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' - - name: status - in: query - required: false - schema: - type: string - enum: - - provisioning - - active - - restoring - - failed - - deleting - description: Return only the databases in this status. + - $ref: '#/components/parameters/FrontendId' responses: '200': - description: Successful response + description: Frontend redeploy started or queued content: application/json: schema: - $ref: '#/components/schemas/PaginatedDatabases' - post: - tags: - - Databases - summary: Create a new serverless PostgreSQL database - description: | - Creates a serverless PostgreSQL database in the project. - Each project can hold 1 database on Hobby and up to 10,000 on Superagent. - Requests over the plan's cap return 403. - operationId: createDatabase - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateDatabaseRequest' - responses: - '201': - description: Database created (provisioning) + $ref: '#/components/schemas/Frontend' + '400': + description: Bad request - invalid identifier content: application/json: schema: - $ref: '#/components/schemas/Database' - '403': - description: Database limit exceeded for the project + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}: - get: - tags: - - Databases - summary: Get database details - operationId: getDatabase - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - responses: - '200': - description: Successful response + '403': + description: Forbidden - project ownership required content: application/json: schema: - $ref: '#/components/schemas/Database' - delete: - tags: - - Databases - summary: Delete a database - description: | - Deletes a database and the instance backing it. When the instance is - removed synchronously the database row is deleted and the response is - `204`. If the instance cannot be deleted right away, the database row - is retained (status `deleting`) and its teardown is handed to the - background reconciler, which retries the deletion and removes the row - once the instance is gone; in that case the response is `202`. The database row is - never dropped while its instance still exists, so an instance is - never orphaned without a record to retry from. - operationId: deleteDatabase - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - responses: - '202': - description: | - Deletion accepted and in progress. The backing instance could not be - removed synchronously, so the database is marked `deleting` and torn - down asynchronously by the reconciler. + $ref: '#/components/schemas/Error' + '404': + description: Frontend not found content: application/json: schema: - type: object - properties: - status: - type: string - example: deleting - message: - type: string - example: database deletion in progress - '204': - description: Database deleted (backing instance removed synchronously) - '404': - description: Project or database not found + $ref: '#/components/schemas/Error' + '409': + description: Conflict - frontend deletion is queued or running content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: | - A restore is running on the database. Deleting it while a worker is - replacing its data would race that worker, so wait for the restore - to finish. + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: | - Volcano could not check whether a restore is running, and will not - delete a database that might be mid-restore. Retry. + description: Service unavailable - frontend workflow configuration missing content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/branches: + /projects/{id}/frontends/{frontendId}/domain: get: tags: - - Database Branches - summary: List a database's branches - description: | - Returns every branch of the database, including those still provisioning - and those that failed, since each still holds a name. - - Connection strings are omitted. Fetch a single branch to get its - connection string. - operationId: listDatabaseBranches + - Frontends + summary: Get frontend custom domain status + operationId: getFrontendCustomDomain security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/FrontendId' responses: '200': - description: Successful response + description: | + Frontend custom domain status, or null when the frontend has no + custom domain configured (the common empty state). content: application/json: schema: - $ref: '#/components/schemas/DatabaseBranchList' + nullable: true + allOf: + - $ref: '#/components/schemas/FrontendCustomDomainResponse' + '400': + description: Bad request - invalid identifier + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - project ownership required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Project or database not found + description: Frontend not found content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Branching is temporarily unavailable + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' post: tags: - - Database Branches - summary: Create a branch of a database + - Frontends + summary: Configure frontend custom domain (SUPERAGENT) description: | - Forks the database into a new branch. The branch starts as an exact copy - of the parent's data and diverges from there. - - Provisioning is asynchronous: the response is `202` with the branch in - `provisioning` and no connection string. Poll the branch until it reports - `active`, at which point it carries its own connection string. - - Retrying a create with a name that already exists returns `409` rather - than a second branch, so a retried request cannot silently consume two - slots of the branch allowance. - operationId: createDatabaseBranch + Configures one custom domain for a frontend. + The default Volcano-generated frontend URL remains active. + Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes. + operationId: createFrontendCustomDomain security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/FrontendId' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/CreateDatabaseBranchRequest' + $ref: '#/components/schemas/CreateFrontendCustomDomainRequest' responses: - '202': - description: Branch accepted and provisioning + '200': + description: Custom domain already configured with same hostname content: application/json: schema: - $ref: '#/components/schemas/DatabaseBranch' - '400': - description: Invalid branch name or lifetime + $ref: '#/components/schemas/FrontendCustomDomainResponse' + '201': + description: Custom domain provisioning started content: application/json: schema: - $ref: '#/components/schemas/Error' - '403': - description: | - The database has reached its branch allowance, or the owner's plan - does not include branching. + $ref: '#/components/schemas/FrontendCustomDomainResponse' + '400': + description: Bad request - invalid domain content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Project or database not found + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: | - A branch of that name already exists on this database, or the - database cannot be branched right now because it is still - provisioning, being restored, failed, or being deleted. + '403': + description: Forbidden - custom domains require SUPERAGENT plan content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Branching is temporarily unavailable + '404': + description: Frontend not found content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/branches/{branchName}: - get: - tags: - - Database Branches - summary: Get a branch - description: | - Returns the branch, including its connection string once it is `active`. - Poll this after creating a branch to learn when it is connectable. - operationId: getDatabaseBranch - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' - responses: - '200': - description: Successful response + '409': + description: Conflict - custom domain already in use, still detaching, or frontend already has a custom domain content: application/json: schema: - $ref: '#/components/schemas/DatabaseBranch' - '404': - description: Project, database, or branch not found + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Branching is temporarily unavailable + description: Service unavailable - custom domain provisioning is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - patch: + delete: tags: - - Database Branches - summary: Extend a branch's lifetime - description: | - Replaces the branch's lifetime and restarts the countdown from now, so a - branch you are still working on is not swept mid-session. The new - duration is remembered, so a later reset re-arms the same lifetime. - operationId: updateDatabaseBranch + - Frontends + summary: Delete frontend custom domain + operationId: deleteFrontendCustomDomain security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateDatabaseBranchRequest' + - $ref: '#/components/parameters/FrontendId' responses: - '200': - description: Lifetime updated + '204': + description: Custom domain detach scheduled + '400': + description: Bad request - invalid identifier content: application/json: schema: - $ref: '#/components/schemas/DatabaseBranch' - '400': - description: Requested lifetime is outside the allowed range + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Project, database, or branch not found + '403': + description: Forbidden - project ownership required content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: The branch is being deleted + '404': + description: Frontend or custom domain not found content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Branching is temporarily unavailable + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /projects/{id}/frontends/{frontendId}/deployments: + get: tags: - - Database Branches - summary: Delete a branch - description: | - Marks the branch for teardown and returns immediately. The branch stops - accepting connections at once; its fork and its row are removed by a - background job, so a provider outage cannot leave the call hanging or the - branch half-deleted. - - Deleting a branch that is still provisioning is allowed and stops the - build, and repeating the call while teardown is in progress is accepted - again. Once the branch is gone the call returns `404`. - operationId: deleteDatabaseBranch + - Frontends + summary: List frontend deployments + operationId: listFrontendDeployments security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' + - $ref: '#/components/parameters/FrontendId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' responses: - '202': - description: Deletion accepted and in progress + '200': + description: Successful response content: application/json: schema: - type: object - properties: - status: - type: string - example: deleting - message: - type: string - example: branch deletion in progress - required: - - status - - message + $ref: '#/components/schemas/PaginatedFrontendDeployments' + '400': + description: Bad request - invalid identifier + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - project ownership required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Project, database, or branch not found + description: Frontend not found content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Branching is temporarily unavailable + '500': + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/branches/{branchName}/reset: - post: + /projects/{id}/frontends/{frontendId}/usage: + get: tags: - - Database Branches - summary: Reset a branch to its parent's current state + - Frontends + summary: Per-day request and error counts for a single frontend description: | - Discards everything written on the branch and re-forks it from the - parent as it is now. - - Returns immediately with the branch in `provisioning`. The rewind runs in - the background; poll the branch until it reports `active` before - connecting again. + Returns a zero-filled daily series of request counts and 5xx + error counts for one frontend, oldest first. Each entry is one + UTC day; missing days (no traffic recorded) come back as + `requests: 0, errors: 0` so the response always has exactly + `days` entries. - The branch keeps its name and its connection string, so anything holding - that string keeps working once it is active again, and its lifetime is - re-armed to the duration it was created with. The branch does not serve - connections for the duration of the reset. - operationId: resetDatabaseBranch + Backs the Monitoring section on the Frontend detail page in + volcano-web. `days` defaults to 30 and is capped at 90 to keep + the (frontend_id, day) index scan bounded. + operationId: getFrontendUsageHistory security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' + - $ref: '#/components/parameters/FrontendId' + - name: days + in: query + description: Number of trailing days to return (1–90, default 30). + required: false + schema: + type: integer + minimum: 1 + maximum: 90 + default: 30 responses: - '202': - description: Branch reset accepted; the branch is provisioning + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseBranch' - '404': - description: Project, database, or branch not found + $ref: '#/components/schemas/FrontendUsageHistoryResponse' + '400': + description: Bad request - invalid identifier content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: | - The branch is not active, a reset is already in progress, the parent - database is being restored, or the parent was restored within the - last 24 hours — a reset re-forks from the parent, and the provider - holds a child's reset shut for that long afterwards. + '401': + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Branching is temporarily unavailable + '403': + description: Forbidden - project ownership required content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/branches/{branchName}/reset-password: - post: + '404': + description: Frontend not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/frontends/{frontendId}/function-routes: + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/FrontendId' + get: tags: - - Database Branches - summary: Rotate a branch's password - description: | - Issues a new password for the branch and invalidates the previous - connection string. Existing connections are not interrupted; new ones - must use the returned string. Proxies pick the rotation up within a few - seconds, so the previous password can still open new connections until - then. - - The parent database's credentials are untouched. - operationId: resetDatabaseBranchPassword + - Frontends + summary: List a Frontend's Function routes + operationId: listFrontendFunctionRoutes security: - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' + - ProjectAccessToken: [] responses: '200': - description: Password rotated + description: Function routes ordered from most to least specific content: application/json: schema: - $ref: '#/components/schemas/DatabaseBranch' - '404': - description: Project, database, or branch not found + $ref: '#/components/schemas/FrontendFunctionRouteList' + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: The branch is not active + '403': + description: Project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Branching is temporarily unavailable + '500': + description: Failed to list Function routes content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/backups: - get: + post: tags: - - Database Backups - summary: List a database's backups - description: | - Returns every backup of the database, newest first, together with the - window a point-in-time restore may target. - - Both backups you took and backups the schedule produced are listed; - `source` tells them apart. Only manual backups count against the plan's - backup allowance. - operationId: listDatabaseBackups + - Frontends + summary: Route a Frontend path to an HTTP Function + operationId: createFrontendFunctionRoute + description: The Frontend and Function must belong to this Project. The Function may be private but must use HTTP invocation mode. The route applies to every hostname that resolves to the Frontend, including generated, custom-domain, preview, and local hostnames. security: - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' + - ProjectAccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateFrontendFunctionRouteRequest' responses: - '200': - description: Successful response + '201': + description: Function route created content: application/json: schema: - $ref: '#/components/schemas/DatabaseBackupList' + $ref: '#/components/schemas/FrontendFunctionRoute' + '400': + description: Invalid path or non-HTTP Function + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '403': - description: Backups are SUPERAGENT-only and the owner's plan does not include them + description: Project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project or database not found + description: Frontend or Function not found in the Project content: application/json: schema: $ref: '#/components/schemas/Error' '409': - description: | - The database has no storage project yet, so there is nothing to - list. A database reports this while it is still provisioning. + description: Path is already routed or the Frontend has reached its 64-route limit content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Backups are temporarily unavailable + '500': + description: Failed to create Function route content: application/json: schema: $ref: '#/components/schemas/Error' - post: + /projects/{id}/frontends/{frontendId}/function-routes/{routeId}: + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/FrontendId' + - $ref: '#/components/parameters/FrontendFunctionRouteId' + put: tags: - - Database Backups - summary: Back up a database - description: | - Captures the database as it is now. The backup is available immediately; - its `size_bytes` appears once the storage provider has costed it. - - Backups are rate-limited to one per minute per database, and capped by - the owner's plan. - operationId: createDatabaseBackup + - Frontends + summary: Replace a Frontend Function route + operationId: updateFrontendFunctionRoute security: - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' + - ProjectAccessToken: [] requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/CreateDatabaseBackupRequest' + $ref: '#/components/schemas/CreateFrontendFunctionRouteRequest' responses: - '201': - description: Backup created + '200': + description: Function route replaced content: application/json: schema: - $ref: '#/components/schemas/DatabaseBackup' + $ref: '#/components/schemas/FrontendFunctionRoute' '400': - description: Invalid backup name - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: | - The database has reached its backup allowance, or the owner's plan - does not include backups, which are SUPERAGENT-only. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project or database not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: | - A backup of that name already exists, the database is not active, a - restore is running on it, or a backup was taken too recently. + description: Invalid path or non-HTTP Function content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Backups are temporarily unavailable + '401': + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/backups/{backupName}: - get: - tags: - - Database Backups - summary: Get a backup - description: Returns one backup of the database. - operationId: getDatabaseBackup - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BackupName' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseBackup' '403': - description: Backups are SUPERAGENT-only and the owner's plan does not include them + description: Project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project, database, or backup not found + description: Function route, Frontend, or Function not found content: application/json: schema: $ref: '#/components/schemas/Error' '409': - description: | - The database has no storage project yet, so it holds no backups. A - database reports this while it is still provisioning. + description: Path is already routed or the Frontend has reached its 64-route limit content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Backups are temporarily unavailable + '500': + description: Failed to replace Function route content: application/json: schema: $ref: '#/components/schemas/Error' delete: tags: - - Database Backups - summary: Delete a backup - description: | - Deletes the backup and frees its storage. Scheduled backups can be - deleted too. A backup that is already gone reports `404`, so a name - that never existed and a name that no longer does read the same. - Refused with `409` while the database is being restored. - operationId: deleteDatabaseBackup + - Frontends + summary: Delete a Frontend Function route + operationId: deleteFrontendFunctionRoute security: - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BackupName' + - ProjectAccessToken: [] responses: - '200': - description: Backup deleted + '204': + description: Function route deleted + '401': + description: Unauthorized content: application/json: schema: - type: object - properties: - status: - type: string - example: deleted - message: - type: string - example: backup deleted - required: - - status - - message + $ref: '#/components/schemas/Error' '403': - description: Backups are SUPERAGENT-only and the owner's plan does not include them + description: Project not owned by the caller content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project, database, or backup not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: | - The database is being restored. A restore is pinned to a backup it - may not have restored yet, so deleting one is refused until the - restore finishes. + description: Function route not found on the Frontend content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Backups are temporarily unavailable + '500': + description: Failed to delete Function route content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/backup-schedule: + /projects/{id}/variables: get: tags: - - Database Backups - summary: Get the automated backup schedule + - Variables + summary: List all variables for a project description: | - Returns the database's backup schedule. An empty list means no scheduled - backups. - operationId: getDatabaseBackupSchedule + Returns project-level environment variables used by deployed functions and frontends. + operationId: listVariables security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseBackupSchedule' - '403': - description: Backups are SUPERAGENT-only and the owner's plan does not include them - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/PaginatedVariables' '404': - description: Project or database not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: | - The database has no storage project yet, so it has no schedule. A - database reports this while it is still provisioning. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '503': - description: Backups are temporarily unavailable + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - put: + post: tags: - - Database Backups - summary: Replace the automated backup schedule + - Variables + summary: Create or update a variable description: | - Replaces the schedule wholesale. Send an empty `entries` list to stop - scheduled backups. - - Scheduled backups do not count against the plan's backup allowance, but - their retention is clamped to the plan's. - operationId: updateDatabaseBackupSchedule + Creates a project-level environment variable and triggers asynchronous propagation + to deployed functions and frontends in the project's configured regions. + operationId: createVariable security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/DatabaseBackupSchedule' + $ref: '#/components/schemas/CreateVariableRequest' responses: - '200': - description: Schedule replaced + '201': + description: Variable created content: application/json: schema: - $ref: '#/components/schemas/DatabaseBackupSchedule' + $ref: '#/components/schemas/Variable' '400': - description: | - The schedule names a recurrence that cannot fire: a weekly or - monthly one with no `day`, or a `day` outside its frequency's range - (1-7 for weekly, 1-28 for monthly). The response says which. - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Backups are SUPERAGENT-only and the owner's plan does not include them - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project or database not found + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: | - The database is not active, or a restore is running on it — a restore - moves the data to a new branch, and the provider keeps the schedule - per branch. + '503': + description: Private variable membership writes are disabled during rollout content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Backups are temporarily unavailable - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/restores: + /projects/{id}/databases: get: tags: - - Database Backups - summary: List a database's restores + - Databases + summary: List all databases for a project description: | - Returns the database's restore history, newest first, capped at the 50 - most recent. There is no pagination: a database that has been restored - more than 50 times keeps the older records but does not return them. - operationId: listDatabaseRestores + Supports two mutually exclusive pagination modes. Offset mode uses `page` + and `limit`. Cursor mode uses `cursor` and `limit`, supports `search` + (case-insensitive name match), and returns `next_cursor`/`prev_cursor`. + The optional `status` filter applies in both modes and is bound to the + cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400. + operationId: listDatabases security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + - name: status + in: query + required: false + schema: + type: string + enum: + - provisioning + - active + - restoring + - failed + - deleting + description: Return only the databases in this status. responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseRestoreList' - '403': - description: Backups are SUPERAGENT-only and the owner's plan does not include them - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project or database not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '503': - description: Backups are temporarily unavailable - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/PaginatedDatabases' post: tags: - - Database Backups - summary: Restore a database + - Databases + summary: Create a new PostgreSQL database description: | - Replaces the database's data, either with a named backup or with its - state at a point in time. This is destructive: everything written after - that point is discarded. - - Asynchronous: the response is `202` with the restore `pending` and the - database `restoring`. The database does not accept connections until the - restore reports `completed`; its connection string is unchanged - throughout, so nothing holding it needs updating. - - Restores are in place. There is no way to restore into a second - database, and a database's branches are never restored — they keep - serving their own data, but resetting a branch from its parent is - refused by the storage provider for up to 24 hours afterwards. - operationId: createDatabaseRestore + Creates a PostgreSQL database in the project. + Each project can hold 1 database on HOBBY and up to 10,000 on SUPERAGENT. + Requests over the plan's cap return 403. + operationId: createDatabase security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/DatabaseName' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/CreateDatabaseRestoreRequest' + $ref: '#/components/schemas/CreateDatabaseRequest' responses: - '202': - description: Restore accepted and in progress + '201': + description: Database created (provisioning) content: application/json: schema: - $ref: '#/components/schemas/DatabaseRestore' - '400': - description: | - Neither or both restore targets were named, or the requested time is - outside the available window. + $ref: '#/components/schemas/Database' + '403': + description: Database limit exceeded for the project content: application/json: schema: $ref: '#/components/schemas/Error' - '403': + /projects/{id}/databases/{databaseName}: + get: + tags: + - Databases + summary: Get database details + operationId: getDatabase + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DatabaseName' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/Database' + delete: + tags: + - Databases + summary: Delete a database + description: | + Deletes a database and the instance backing it. When the instance is + removed synchronously the database row is deleted and the response is + `204`. If the instance cannot be deleted right away, the database row + is retained (status `deleting`) and its teardown is handed to the + background reconciler, which retries the deletion and removes the row + once the instance is gone; in that case the response is `202`. The database row is + never dropped while its instance still exists, so an instance is + never orphaned without a record to retry from. + operationId: deleteDatabase + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DatabaseName' + responses: + '202': description: | - The owner's plan does not include backups or point-in-time restore. - Both are SUPERAGENT-only. + Deletion accepted and in progress. The backing instance could not be + removed synchronously, so the database is marked `deleting` and torn + down asynchronously by the reconciler. content: application/json: schema: - $ref: '#/components/schemas/Error' + type: object + properties: + status: + type: string + example: deleting + message: + type: string + example: database deletion in progress + '204': + description: Database deleted (backing instance removed synchronously) '404': - description: Project, database, or backup not found + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' '409': description: | - A restore is already in progress, the database is not active, - another database operation is still running, or the database is - holding as many pre-restore branches as it may. + A restore is running on the database. Deleting it while a worker is + replacing its data would race that worker, so wait for the restore + to finish. content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Backups are temporarily unavailable + description: | + Volcano could not check whether a restore is running, and will not + delete a database that might be mid-restore. Retry. content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/restores/{restoreId}: + /projects/{id}/databases/{databaseName}/branches: get: tags: - - Database Backups - summary: Get a restore + - Database Branches + summary: List a database's branches description: | - Returns the restore. Poll this after starting one; the database is - connectable again once it reports `completed`. - operationId: getDatabaseRestore + Returns every branch of the database, including those still provisioning + and those that failed, since each still holds a name. + + Connection strings are omitted. Fetch a single branch to get its + connection string. + operationId: listDatabaseBranches security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/RestoreId' responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseRestore' - '403': - description: Backups are SUPERAGENT-only and the owner's plan does not include them - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/DatabaseBranchList' '404': - description: Project, database, or restore not found + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Backups are temporarily unavailable + description: Branching is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/reset-password: post: tags: - - Databases - summary: Reset database password + - Database Branches + summary: Create a branch of a database description: | - Rotates the Volcano-managed PostgreSQL password used by clients when connecting - through pgproxy. This does not rotate or expose the internal owner password. - The returned password and connection string are the only client credentials that - will authenticate through pgproxy after reset. + Forks the database into a new branch. The branch starts as an exact copy + of the parent's data and diverges from there. - Existing connections are not interrupted; new ones must use the returned - string. Proxies pick the rotation up within a few seconds, so the previous - password can still open new connections until then. - operationId: resetDatabasePassword + Provisioning is asynchronous: the response is `202` with the branch in + `provisioning` and no connection string. Poll the branch until it reports + `active`, at which point it carries its own connection string. + + Retrying a create with a name that already exists returns `409` rather + than a second branch, so a retried request cannot silently consume two + slots of the branch allowance. + operationId: createDatabaseBranch security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDatabaseBranchRequest' responses: - '200': - description: Password reset successful + '202': + description: Branch accepted and provisioning content: application/json: schema: - type: object - properties: - message: - type: string - role_name: - type: string - description: Volcano-managed per-database client login (also the pgproxy routing username) - example: volcano_client_11111111-1111-1111-1111-111111111111 - new_password: - type: string - description: New Volcano-managed client password. Always starts with `vpg_`. - connection_string: - type: string - description: Updated pgproxy connection string using Volcano-managed credentials. + $ref: '#/components/schemas/DatabaseBranch' '400': - description: Database is not active + description: Invalid branch name or lifetime + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: | + The database has reached its branch allowance, or the owner's plan + does not include branching. content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Database not found + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' '409': description: | - A restore is running on the database. A restore replaces the - credentials as it finishes, so wait for it and rotate afterwards. + A branch of that name already exists on this database, or the + database cannot be branched right now because it is still + provisioning, being restored, failed, or being deleted. content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: | - Volcano could not check whether a restore is running, and will not - rotate a credential a restore might be about to replace. Retry. + description: Branching is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/type: - patch: + /projects/{id}/databases/{databaseName}/branches/{branchName}: + get: tags: - - Databases - summary: Update database size + - Database Branches + summary: Get a branch description: | - Change the size tier of a database. This may briefly interrupt active connections. - - **Available sizes:** - - `volcano-db-xs`: Up to ~1GB RAM - Development, small apps - - `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic - - `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications - - `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets - - `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads - - `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale - operationId: updateDatabaseType + Returns the branch, including its connection string once it is `active`. + Poll this after creating a branch to learn when it is connectable. + operationId: getDatabaseBranch security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateDatabaseTypeRequest' + - $ref: '#/components/parameters/BranchName' responses: '200': - description: Database type updated + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Database' - '400': - description: Invalid database type + $ref: '#/components/schemas/DatabaseBranch' '404': - description: Database not found - '409': - description: | - The database is not active — being provisioned, deleted, or - restored. Compute can only be changed while it is active. + description: Project, database, or branch not found content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: | - Volcano could not check whether a restore is running, and will not - reconfigure compute a restore might be moving. Retry. + description: Branching is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/databases/{databaseName}/stats: - get: + patch: tags: - - Databases - summary: Get database consumption metrics + - Database Branches + summary: Extend a branch's lifetime description: | - Retrieve consumption metrics including storage, compute time, and data transfer. - Metrics are aggregated at the project level. Defaults to last 24 hours. - - **Note:** Advanced metrics require an upgraded plan. - operationId: getDatabaseStats + Replaces the branch's lifetime and restarts the countdown from now, so a + branch you are still working on is not swept mid-session. The new + duration is remembered, so a later reset re-arms the same lifetime. + operationId: updateDatabaseBranch security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - - name: from - in: query - required: false - schema: - type: string - format: date-time - description: Start time in RFC3339 format (e.g., "2024-01-01T00:00:00Z"). Defaults to 24 hours ago. - - name: to - in: query - required: false - schema: - type: string - format: date-time - description: End time in RFC3339 format (e.g., "2024-01-02T00:00:00Z"). Defaults to now. - - name: granularity - in: query - required: false - schema: - type: string - enum: - - hourly - - daily - - monthly - default: hourly - description: Level of detail for metrics aggregation + - $ref: '#/components/parameters/BranchName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateDatabaseBranchRequest' responses: '200': - description: Successful response + description: Lifetime updated content: application/json: schema: - $ref: '#/components/schemas/DatabaseStats' + $ref: '#/components/schemas/DatabaseBranch' '400': - description: Invalid parameters + description: Requested lifetime is outside the allowed range content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Database not found + description: Project, database, or branch not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: The branch is being deleted content: application/json: schema: $ref: '#/components/schemas/Error' '503': - description: Database metrics not available or requires upgraded plan + description: Branching is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - /databases/{databaseName}/query/ping: - post: + delete: tags: - - Database Queries - summary: Database connectivity probe (REST API) + - Database Branches + summary: Delete a branch description: | - Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the - same authentication, status/bandwidth gating, and metering as the other - `/query/*` endpoints. + Marks the branch for teardown and returns immediately. The branch stops + accepting connections at once; its fork and its row are removed by a + background job, so a provider outage cannot leave the call hanging or the + branch half-deleted. - Unlike those endpoints, ping takes **no request body** and performs **no - table-name validation**, so it works on any database — including a freshly - provisioned, empty one. It is a real committed round-trip through pgproxy, - so a `200` means the database is reachable and queryable. Used by the - dashboard's database connection test. - operationId: queryDatabasePing + Deleting a branch that is still provisioning is allowed and stops the + build, and repeating the call while teardown is in progress is accepted + again. Once the branch is gone the call returns `404`. + operationId: deleteDatabaseBranch security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/BranchName' responses: - '200': - description: Database is reachable - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - '?column?': 1 - count: 1 - '401': - description: Not authenticated + '202': + description: Deletion accepted and in progress content: application/json: schema: - $ref: '#/components/schemas/Error' - '403': - description: Access denied + type: object + properties: + status: + type: string + example: deleting + message: + type: string + example: branch deletion in progress + required: + - status + - message + '404': + description: Project, database, or branch not found content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database not found + '503': + description: Branching is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - /databases/{databaseName}/query/select: + /projects/{id}/databases/{databaseName}/branches/{branchName}/reset: post: tags: - - Database Queries - summary: Query database with SELECT (REST API) + - Database Branches + summary: Reset a branch to its parent's current state description: | - Query your database using a simple REST API - no SQL required! - - **Authentication:** Requires auth user access token (from signup/signin) - - **Row-Level Security:** Automatically enforced - you see only data you have access to + Discards everything written on the branch and re-forks it from the + parent as it is now. - **Use Cases:** - - Query from browser/mobile apps - - Simple data retrieval - - Filtered searches with sorting and pagination + Returns immediately with the branch in `provisioning`. The rewind runs in + the background; poll the branch until it reports `active` before + connecting again. - **Note:** For complex queries (JOINs, CTEs), use functions with direct SQL - operationId: queryDatabaseSelect + The branch keeps its name and its connection string, so anything holding + that string keeps working once it is active again, and its lifetime is + re-armed to the duration it was created with. The branch does not serve + connections for the duration of the reset. + operationId: resetDatabaseBranch security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseSelectRequest' + - $ref: '#/components/parameters/BranchName' responses: - '200': - description: Query successful - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: uuid-123 - title: My Post - content: Post content - status: published - views: 150 - created_at: '2026-01-13T10:00:00Z' - count: 1 - '400': - description: Invalid query + '202': + description: Branch reset accepted; the branch is provisioning content: application/json: schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + $ref: '#/components/schemas/DatabaseBranch' + '404': + description: Project, database, or branch not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '409': + description: | + The branch is not active, a reset is already in progress, the parent + database is being restored, or the parent was restored within the + last 24 hours — a reset re-forks from the parent, and the provider + holds a child's reset shut for that long afterwards. content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database not found + '503': + description: Branching is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - /databases/{databaseName}/query/insert: + /projects/{id}/databases/{databaseName}/branches/{branchName}/reset-password: post: tags: - - Database Queries - summary: Insert data into database (REST API) + - Database Branches + summary: Rotate a branch's password description: | - Insert new rows into your database using REST API. - - **Authentication:** Requires auth user access token - - **Auto-set user_id:** If your table has a trigger using `auth.uid()`, - user_id will be automatically set to the authenticated user + Issues a new password for the branch and invalidates the previous + connection string. Existing connections are not interrupted; new ones + must use the returned string. Proxies pick the rotation up within a few + seconds, so the previous password can still open new connections until + then. - **Security:** Row-Level Security policies are enforced - operationId: queryDatabaseInsert + The parent database's credentials are untouched. + operationId: resetDatabaseBranchPassword security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseInsertRequest' + - $ref: '#/components/parameters/BranchName' responses: '200': - description: Insert successful - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: uuid-123 - title: My New Post - content: This is the content - status: draft - user_id: user-uuid - created_at: '2026-01-13T10:00:00Z' - count: 1 - '400': - description: Invalid request + description: Password rotated content: application/json: schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + $ref: '#/components/schemas/DatabaseBranch' + '404': + description: Project, database, or branch not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '409': + description: The branch is not active content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database not found + '503': + description: Branching is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - /databases/{databaseName}/query/update: - post: + /projects/{id}/databases/{databaseName}/backups: + get: tags: - - Database Queries - summary: Update data in database (REST API) + - Database Backups + summary: List a database's backups description: | - Update existing rows in your database using REST API. - - **Security:** Row-Level Security ensures you can only update data you have access to - - **Safety:** Requires at least one filter to prevent accidental mass updates. A - request with no `filters` is rejected with `400` (mirrors delete). This matters - for service-key queries, which run with full access and bypass RLS. + Returns every backup of the database, newest first, together with the + window a point-in-time restore may target. - **Note:** If RLS blocks the update, an empty result is returned (not an error) - operationId: queryDatabaseUpdate + Both backups you took and backups the schedule produced are listed; + `source` tells them apart. Only manual backups count against the plan's + backup allowance. + operationId: listDatabaseBackups security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseUpdateRequest' responses: '200': - description: Update successful + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: post-uuid - title: Updated Title - status: published - updated_at: '2026-01-13T10:05:00Z' - count: 1 - '400': - description: Invalid request + $ref: '#/components/schemas/DatabaseBackupList' + '403': + description: Backups require SUPERAGENT content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '404': + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '409': + description: | + The database has no storage project yet, so there is nothing to + list. A database reports this while it is still provisioning. content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database not found + '503': + description: Backups are temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - /databases/{databaseName}/query/delete: post: tags: - - Database Queries - summary: Delete data from database (REST API) + - Database Backups + summary: Back up a database description: | - Delete rows from your database using REST API. - - **Safety:** Requires at least one filter to prevent accidental mass deletions - - **Security:** Row-Level Security ensures you can only delete data you have access to + Captures the database as it is now. The backup is available immediately; + its `size_bytes` appears once the storage provider has costed it. - **Note:** If RLS blocks the delete, an empty result is returned (not an error) - operationId: queryDatabaseDelete + Backups are rate-limited to one per minute per database, and capped by + the owner's plan. + operationId: createDatabaseBackup security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/DatabaseDeleteRequest' + $ref: '#/components/schemas/CreateDatabaseBackupRequest' responses: - '200': - description: Delete successful + '201': + description: Backup created content: application/json: schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: post-uuid - title: Deleted Post - count: 1 + $ref: '#/components/schemas/DatabaseBackup' '400': - description: Invalid request or missing filters + description: Invalid backup name content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '403': + description: | + The database has reached its backup allowance, or the owner's plan + does not include backups, which are available only on SUPERAGENT. content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '404': + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database not found + '409': + description: | + A backup of that name already exists, the database is not active, a + restore is running on it, or a backup was taken too recently. content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - /databases/{databaseName}/branches/{branchName}/query/ping: - post: + '503': + description: Backups are temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/databases/{databaseName}/backups/{backupName}: + get: tags: - - Database Queries - summary: Database connectivity probe (REST API) - description: | - Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the - same authentication, status/bandwidth gating, and metering as the other - `/query/*` endpoints. - - Unlike those endpoints, ping takes **no request body** and performs **no - table-name validation**, so it works on any database — including a freshly - provisioned, empty one. It is a real committed round-trip through pgproxy, - so a `200` means the database is reachable and queryable. Used by the - dashboard's database connection test. - - **Branch-targeted.** Runs against the named branch instead of the parent - database, using the branch's own credentials. The branch must be `active` - and unexpired. Nothing about this request can reach the parent's data. - operationId: queryDatabaseBranchPing + - Database Backups + summary: Get a backup + description: Returns one backup of the database. + operationId: getDatabaseBackup security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' + - $ref: '#/components/parameters/BackupName' responses: '200': - description: Database is reachable + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - '?column?': 1 - count: 1 - '401': - description: Not authenticated + $ref: '#/components/schemas/DatabaseBackup' + '403': + description: Backups require SUPERAGENT content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '404': + description: Project, database, or backup not found content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database or branch not found + '409': + description: | + The database has no storage project yet, so it holds no backups. A + database reports this while it is still provisioning. content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' '503': - $ref: '#/components/responses/DatabaseBranchQueryUnavailable' - /databases/{databaseName}/branches/{branchName}/query/select: - post: + description: Backups are temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: tags: - - Database Queries - summary: Query database with SELECT (REST API) + - Database Backups + summary: Delete a backup description: | - Query your database using a simple REST API - no SQL required! - - **Authentication:** Requires auth user access token (from signup/signin) - - **Row-Level Security:** Automatically enforced - you see only data you have access to - - **Use Cases:** - - Query from browser/mobile apps - - Simple data retrieval - - Filtered searches with sorting and pagination - - **Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL - - **Branch-targeted.** Runs against the named branch instead of the parent - database, using the branch's own credentials. The branch must be `active` - and unexpired. Nothing about this request can reach the parent's data. - operationId: queryDatabaseBranchSelect + Deletes the backup and frees its storage. Scheduled backups can be + deleted too. A backup that is already gone reports `404`, so a name + that never existed and a name that no longer does read the same. + Refused with `409` while the database is being restored. + operationId: deleteDatabaseBackup security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseSelectRequest' + - $ref: '#/components/parameters/BackupName' responses: '200': - description: Query successful + description: Backup deleted content: application/json: schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: uuid-123 - title: My Post - content: Post content - status: published - views: 150 - created_at: '2026-01-13T10:00:00Z' - count: 1 - '400': - description: Invalid query + type: object + properties: + status: + type: string + example: deleted + message: + type: string + example: backup deleted + required: + - status + - message + '403': + description: Backups require SUPERAGENT content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '404': + description: Project, database, or backup not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '409': + description: | + The database is being restored. A restore is pinned to a backup it + may not have restored yet, so deleting one is refused until the + restore finishes. content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database or branch not found + '503': + description: Backups are temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - '503': - $ref: '#/components/responses/DatabaseBranchQueryUnavailable' - /databases/{databaseName}/branches/{branchName}/query/insert: - post: + /projects/{id}/databases/{databaseName}/backup-schedule: + get: tags: - - Database Queries - summary: Insert data into database (REST API) + - Database Backups + summary: Get the automated backup schedule description: | - Insert new rows into your database using REST API. - - **Authentication:** Requires auth user access token - - **Auto-set user_id:** If your table has a trigger using `auth.uid()`, - user_id will be automatically set to the authenticated user - - **Security:** Row-Level Security policies are enforced - - **Branch-targeted.** Runs against the named branch instead of the parent - database, using the branch's own credentials. The branch must be `active` - and unexpired. Nothing about this request can reach the parent's data. - operationId: queryDatabaseBranchInsert + Returns the database's backup schedule. An empty list means no scheduled + backups. + operationId: getDatabaseBackupSchedule security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseInsertRequest' responses: '200': - description: Insert successful + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: uuid-123 - title: My New Post - content: This is the content - status: draft - user_id: user-uuid - created_at: '2026-01-13T10:00:00Z' - count: 1 - '400': - description: Invalid request + $ref: '#/components/schemas/DatabaseBackupSchedule' + '403': + description: Backups require SUPERAGENT content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '404': + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '409': + description: | + The database has no storage project yet, so it has no schedule. A + database reports this while it is still provisioning. content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database or branch not found + '503': + description: Backups are temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - '503': - $ref: '#/components/responses/DatabaseBranchQueryUnavailable' - /databases/{databaseName}/branches/{branchName}/query/update: - post: + put: tags: - - Database Queries - summary: Update data in database (REST API) + - Database Backups + summary: Replace the automated backup schedule description: | - Update existing rows in your database using REST API. - - **Security:** Row-Level Security ensures you can only update data you have access to - - **Safety:** Requires at least one filter to prevent accidental mass updates. A - request with no `filters` is rejected with `400` (mirrors delete). This matters - for service-key queries, which run with full access and bypass RLS. - - **Note:** If RLS blocks the update, an empty result is returned (not an error) + Replaces the schedule wholesale. Send an empty `entries` list to stop + scheduled backups. - **Branch-targeted.** Runs against the named branch instead of the parent - database, using the branch's own credentials. The branch must be `active` - and unexpired. Nothing about this request can reach the parent's data. - operationId: queryDatabaseBranchUpdate + Scheduled backups do not count against the plan's backup allowance, but + their retention is clamped to the plan's. + operationId: updateDatabaseBackupSchedule security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/DatabaseUpdateRequest' + $ref: '#/components/schemas/DatabaseBackupSchedule' responses: '200': - description: Update successful + description: Schedule replaced content: application/json: schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: post-uuid - title: Updated Title - status: published - updated_at: '2026-01-13T10:05:00Z' - count: 1 + $ref: '#/components/schemas/DatabaseBackupSchedule' '400': - description: Invalid request + description: | + The schedule names a recurrence that cannot fire: a weekly or + monthly one with no `day`, or a `day` outside its frequency's range + (1-7 for weekly, 1-28 for monthly). The response says which. content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '403': + description: Backups require SUPERAGENT content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '404': + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database or branch not found + '409': + description: | + The database is not active, or a restore is running on it — a restore + moves the data to a new branch, and the provider keeps the schedule + per branch. content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' '503': - $ref: '#/components/responses/DatabaseBranchQueryUnavailable' - /databases/{databaseName}/branches/{branchName}/query/delete: - post: + description: Backups are temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/databases/{databaseName}/restores: + get: tags: - - Database Queries - summary: Delete data from database (REST API) + - Database Backups + summary: List a database's restores description: | - Delete rows from your database using REST API. - - **Safety:** Requires at least one filter to prevent accidental mass deletions - - **Security:** Row-Level Security ensures you can only delete data you have access to - - **Note:** If RLS blocks the delete, an empty result is returned (not an error) - - **Branch-targeted.** Runs against the named branch instead of the parent - database, using the branch's own credentials. The branch must be `active` - and unexpired. Nothing about this request can reach the parent's data. - operationId: queryDatabaseBranchDelete + Returns the database's restore history, newest first, capped at the 50 + most recent. There is no pagination: a database that has been restored + more than 50 times keeps the older records but does not return them. + operationId: listDatabaseRestores security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: + - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DatabaseName' - - $ref: '#/components/parameters/BranchName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDeleteRequest' responses: '200': - description: Delete successful + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/DatabaseQueryResult' - example: - data: - - id: post-uuid - title: Deleted Post - count: 1 - '400': - description: Invalid request or missing filters + $ref: '#/components/schemas/DatabaseRestoreList' + '403': + description: Backups require SUPERAGENT content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '404': + description: Project or database not found content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: Access denied + '503': + description: Backups are temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Database or branch not found + post: + tags: + - Database Backups + summary: Restore a database + description: | + Replaces the database's data, either with a named backup or with its + state at a point in time. This is destructive: everything written after + that point is discarded. + + Asynchronous: the response is `202` with the restore `pending` and the + database `restoring`. The database does not accept connections until the + restore reports `completed`; its connection string is unchanged + throughout, so nothing holding it needs updating. + + Restores are in place. There is no way to restore into a second + database, and a database's branches are never restored — they keep + serving their own data, but resetting a branch from its parent is + refused by the storage provider for up to 24 hours afterwards. + operationId: createDatabaseRestore + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DatabaseName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDatabaseRestoreRequest' + responses: + '202': + description: Restore accepted and in progress + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseRestore' + '400': + description: | + Neither or both restore targets were named, or the requested time is + outside the available window. content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - $ref: '#/components/responses/DatabaseQueryCapExceeded' - '503': - $ref: '#/components/responses/DatabaseBranchQueryUnavailable' - /databases/regions: - get: - tags: - - Databases - summary: List platform-supported regions for database provisioning - operationId: listDatabaseRegions - description: | - Returns the regions enabled for database provisioning in this platform environment. - These are the same regions offered for function deployment, and the only values - the `region` field of a database accepts. - This is a public endpoint that doesn't require authentication. - responses: - '200': - description: List of platform-supported regions + '403': + description: | + The owner's plan does not include backups or point-in-time restore. + Both are available only on SUPERAGENT. content: application/json: schema: - type: array - items: - type: object - properties: - id: - type: string - example: aws-us-east-1 - description: Region identifier for API usage - name: - type: string - example: US East (N. Virginia) - description: Human-readable region location - /databases/postgres-versions: - get: - tags: - - Databases - summary: List available PostgreSQL versions - operationId: listPostgresVersions - description: | - Returns a list of supported PostgreSQL major versions for database provisioning. - This is a public endpoint that doesn't require authentication. - responses: - '200': - description: List of available PostgreSQL versions + $ref: '#/components/schemas/Error' + '404': + description: Project, database, or backup not found content: application/json: schema: - type: array - items: - type: object - properties: - version: - type: string - example: '16' - description: PostgreSQL major version number - name: - type: string - example: PostgreSQL 16 - description: Human-readable version name - default: - type: boolean - description: Whether this is the default version (recommended) - deprecated: - type: boolean - description: Whether this version is deprecated (approaching EOL) - /functions/runtimes: - get: - tags: - - Functions - summary: List supported function runtimes - operationId: listFunctionRuntimes - security: [] - description: | - Returns the public function runtime catalog used by CLI clients to select supported runtimes, - language defaults, and local source packaging metadata for deployments. - This is a public endpoint that doesn't require authentication. - responses: - '200': - description: Supported function runtimes + $ref: '#/components/schemas/Error' + '409': + description: | + A restore is already in progress, the database is not active, + another database operation is still running, or the database is + holding as many pre-restore branches as it may. content: application/json: schema: - $ref: '#/components/schemas/FunctionRuntimesResponse' - /functions/regions: - get: - tags: - - Functions - summary: List available regions for function deployment - operationId: listFunctionRegions - security: [] - description: | - Returns the configured regions where functions can be deployed, each annotated - with a human-readable label and country flag emoji for use in UI pickers. - This is a public endpoint that doesn't require authentication. - responses: - '200': - description: Available function deployment regions + $ref: '#/components/schemas/Error' + '503': + description: Backups are temporarily unavailable content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/FunctionRegion' - /projects/{id}/variables/{name}: + $ref: '#/components/schemas/Error' + /projects/{id}/databases/{databaseName}/restores/{restoreId}: get: tags: - - Variables - summary: Get variable by name + - Database Backups + summary: Get a restore description: | - Returns a project-level environment variable used by deployed functions and frontends. - operationId: getVariable + Returns the restore. Poll this after starting one; the database is + connectable again once it reports `completed`. + operationId: getDatabaseRestore security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/VariableName' + - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/RestoreId' responses: '200': description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Variable' + $ref: '#/components/schemas/DatabaseRestore' + '403': + description: Backups require SUPERAGENT + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Variable not found + description: Project, database, or restore not found content: application/json: schema: $ref: '#/components/schemas/Error' - put: + '503': + description: Backups are temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/databases/{databaseName}/reset-password: + post: tags: - - Variables - summary: Update a variable + - Databases + summary: Reset database password description: | - Updates a project-level environment variable and triggers asynchronous propagation - to deployed functions and frontends in the project's configured regions. - operationId: updateVariable + Rotates the Volcano-managed PostgreSQL password used by clients when connecting + through pgproxy. This does not rotate or expose the internal owner password. + The returned password and connection string are the only client credentials that + will authenticate through pgproxy after reset. + + Existing connections are not interrupted; new ones must use the returned + string. Proxies pick the rotation up within a few seconds, so the previous + password can still open new connections until then. + operationId: resetDatabasePassword security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/VariableName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateVariableRequest' + - $ref: '#/components/parameters/DatabaseName' responses: '200': - description: Variable updated + description: Password reset successful content: application/json: schema: - $ref: '#/components/schemas/Variable' + type: object + properties: + message: + type: string + role_name: + type: string + description: Volcano-managed per-database client login (also the pgproxy routing username) + example: volcano_client_11111111-1111-1111-1111-111111111111 + new_password: + type: string + description: New Volcano-managed client password. Always starts with `vpg_`. + connection_string: + type: string + description: Updated pgproxy connection string using Volcano-managed credentials. + '400': + description: Database is not active + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Variable not found + description: Database not found content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Private variable membership writes are disabled during rollout + '409': + description: | + A restore is running on the database. A restore replaces the + credentials as it finishes, so wait for it and rotate afterwards. content: application/json: schema: $ref: '#/components/schemas/Error' - delete: - tags: - - Variables - summary: Delete a variable - description: | - Deletes a project-level environment variable and triggers asynchronous propagation - of the removal to deployed functions and frontends in the project's configured regions. - operationId: deleteVariable - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/VariableName' - responses: - '204': - description: Variable deleted - '404': - description: Variable not found + '503': + description: | + Volcano could not check whether a restore is running, and will not + rotate a credential a restore might be about to replace. Retry. content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/password-policy: + /projects/{id}/databases/{databaseName}/type: + patch: + tags: + - Databases + summary: Update database size + description: | + Change the size tier of a database. This may briefly interrupt active connections. + + **Available sizes:** + - `volcano-db-xs`: Up to ~1GB RAM - Development, small apps + - `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic + - `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications + - `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets + - `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads + - `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale + operationId: updateDatabaseType + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DatabaseName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateDatabaseTypeRequest' + responses: + '200': + description: Database type updated + content: + application/json: + schema: + $ref: '#/components/schemas/Database' + '400': + description: Invalid database type + '404': + description: Database not found + '409': + description: | + The database is not active — being provisioned, deleted, or + restored. Compute can only be changed while it is active. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: | + Volcano could not check whether a restore is running, and will not + reconfigure compute a restore might be moving. Retry. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/databases/{databaseName}/stats: get: tags: - - Authentication - summary: Get the effective password policy + - Databases + summary: Get database consumption metrics description: | - Returns the backend-enforced password bounds and compromised-password - screening status for the project identified by the anon key. A valid - anon key is required, but no route-specific auth permission is needed. - operationId: authGetPasswordPolicy + Retrieve consumption metrics including storage, compute time, and data transfer. + Metrics are aggregated at the project level. Defaults to last 24 hours. + + **Note:** Advanced metrics require an upgraded plan. + operationId: getDatabaseStats security: - - AnonKey: [] + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/DatabaseName' + - name: from + in: query + required: false + schema: + type: string + format: date-time + description: Start time in RFC3339 format (e.g., "2024-01-01T00:00:00Z"). Defaults to 24 hours ago. + - name: to + in: query + required: false + schema: + type: string + format: date-time + description: End time in RFC3339 format (e.g., "2024-01-02T00:00:00Z"). Defaults to now. + - name: granularity + in: query + required: false + schema: + type: string + enum: + - hourly + - daily + - monthly + default: hourly + description: Level of detail for metrics aggregation responses: '200': - description: Effective password policy + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/AuthPasswordPolicy' - '401': - description: Invalid, missing, or revoked anon key + $ref: '#/components/schemas/DatabaseStats' + '400': + description: Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project or auth configuration not found + description: Database not found content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/signup: + '503': + description: Database metrics not available or requires upgraded plan + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /databases/{databaseName}/query/ping: post: tags: - - Authentication - summary: Sign up a new auth user + - Database Queries + summary: Database connectivity probe (REST API) description: | - Create a new end-user account. The project is determined from the anon key. - Requires project-specific anon key in Authorization header. - - **Session-less**: signup never issues a session. On success it returns a - uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client - obtains a session with a subsequent `POST /auth/signin`. If email confirmation - is enabled for the project, a confirmation email is sent and - `confirmation_required` is `true`. + Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the + same authentication, status/bandwidth gating, and metering as the other + `/query/*` endpoints. - **Anti-enumeration**: a signup for an already-registered email returns the - exact same `201` response as a fresh signup — it never returns `409` — so the - response cannot be used to discover which emails are registered. - operationId: authSignup + Unlike those endpoints, ping takes **no request body** and performs **no + table-name validation**, so it works on any database — including a freshly + provisioned, empty one. It is a real committed round-trip through pgproxy, + so a `200` means the database is reachable and queryable. Used by the + dashboard's database connection test. + operationId: queryDatabasePing security: - - AnonKey: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - email - - password - properties: - email: - type: string - format: email - password: - type: string - description: | - Password validated after NFC normalization against the - policy returned by GET /auth/password-policy. - user_metadata: - type: object - additionalProperties: true + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' responses: - '201': - description: | - Signup acknowledged (session-less). Returned identically for a new - account and for an already-registered email (anti-enumeration). + '200': + description: Database is reachable + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - $ref: '#/components/schemas/AuthSignupResponse' - '400': - description: Invalid input (bad email/password format) + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - '?column?': 1 + count: 1 '401': - description: | - Unauthorized - Invalid, tampered, revoked, or wrong-project anon key + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '403': - description: | - Forbidden - Signups disabled, anon key lacks signup permission, or the - email domain is not in `allowed_email_domains`. The internal - `anonymous.volcano.internal` domain is reserved for anonymous - accounts and is refused whatever the project allows. - '429': - description: Rate limit exceeded - '503': - description: Compromised-password screening is temporarily unavailable + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/signin: + '404': + description: Database not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + /databases/{databaseName}/query/select: post: tags: - - Authentication - summary: Sign in an auth user + - Database Queries + summary: Query database with SELECT (REST API) description: | - Authenticate with email and password. Requires an anon key. + Query your database using a simple REST API - no SQL required! - Set `session_mode` to `cookie` to request HttpOnly refresh-token - storage. Cookie mode is honored only for an exact, credentialed CORS - origin on the same schemeful site as this API. Otherwise the response - retains the refresh token in its body. - operationId: authSignin + **Authentication:** Requires auth user access token (from signup/signin) + + **Row-Level Security:** Automatically enforced - you see only data you have access to + + **Use Cases:** + - Query from browser/mobile apps + - Simple data retrieval + - Filtered searches with sorting and pagination + + **Note:** For complex queries (JOINs, CTEs), use functions with direct SQL + operationId: queryDatabaseSelect security: - - AnonKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' requestBody: required: true content: application/json: schema: - type: object - required: - - email - - password - properties: - email: - type: string - password: - type: string - session_mode: - type: string - enum: - - cookie + $ref: '#/components/schemas/DatabaseSelectRequest' responses: '200': - description: Signin successful + description: Query successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - $ref: '#/components/schemas/AuthTokenResponse' - '400': - description: Invalid input (missing email/password) - '401': - description: | - Unauthorized - Invalid credentials, invalid/tampered/revoked anon key, - or account banned/deleted + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: uuid-123 + title: My Post + content: Post content + status: published + views: 150 + created_at: '2026-01-13T10:00:00Z' + count: 1 + '400': + description: Invalid query + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '403': - description: | - Forbidden - Anon key lacks signin permission, or the email domain is - not in `allowed_email_domains` while `allowed_email_domains_mode` is - `signup_and_signin`. The domain is taken from the account's canonical - email (its primary identity), which is not necessarily the address in - the request. + description: Access denied + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Database not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '429': - description: Rate limit exceeded - /auth/refresh: + $ref: '#/components/responses/DatabaseQueryCapExceeded' + /databases/{databaseName}/query/insert: post: tags: - - Authentication - summary: Refresh access token + - Database Queries + summary: Insert data into database (REST API) description: | - Get a new access token using a refresh token. Requires an anon key. + Insert new rows into your database using REST API. - Send `refresh_token` in the body for the default flow. An eligible - cookie-mode browser request may instead send `session_mode: cookie` - with an empty token or omit the request body; the API reads and resets - the project's HttpOnly cookie and omits `refresh_token` from the - response. - operationId: authRefresh + **Authentication:** Requires auth user access token + + **Auto-set user_id:** If your table has a trigger using `auth.uid()`, + user_id will be automatically set to the authenticated user + + **Security:** Row-Level Security policies are enforced + operationId: queryDatabaseInsert security: - - AnonKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' requestBody: - required: false + required: true content: application/json: schema: - type: object - properties: - refresh_token: - type: string - session_mode: - type: string - enum: - - cookie + $ref: '#/components/schemas/DatabaseInsertRequest' responses: '200': - description: Token refreshed + description: Insert successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - $ref: '#/components/schemas/AuthTokenResponse' + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: uuid-123 + title: My New Post + content: This is the content + status: draft + user_id: user-uuid + created_at: '2026-01-13T10:00:00Z' + count: 1 + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '401': - description: Invalid or expired refresh token + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: | - The account's email domain is not in `allowed_email_domains` while - `allowed_email_domains_mode` is `signup_and_signin`, so the session - cannot be extended + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - description: Rate limit exceeded + '404': + description: Database not found content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/logout: + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + /databases/{databaseName}/query/update: post: tags: - - Authentication - summary: Logout (revoke refresh token) + - Database Queries + summary: Update data in database (REST API) description: | - Invalidate a refresh token. Requires an anon key. + Update existing rows in your database using REST API. - Send `refresh_token` for the default flow. An eligible cookie-mode - browser request may instead send `session_mode: cookie` with an empty - token; logout remains idempotent when the cookie is missing or expired. - operationId: authLogout - security: - - AnonKey: [] - requestBody: - required: false - content: - application/json: - schema: - type: object - properties: - refresh_token: - type: string - session_mode: - type: string - enum: - - cookie - responses: - '204': - description: Logged out successfully - /auth/forgot-password: - post: - tags: - - Authentication - summary: Request password reset - description: | - Generates recovery token and stores it (email sending pending). - Returns generic message to prevent email enumeration. - Project is identified via the anon key. - operationId: authForgotPassword + **Security:** Row-Level Security ensures you can only update data you have access to + + **Safety:** Requires at least one filter to prevent accidental mass updates. A + request with no `filters` is rejected with `400` (mirrors delete). This matters + for service-key queries, which run with full access and bypass RLS. + + **Note:** If RLS blocks the update, an empty result is returned (not an error) + operationId: queryDatabaseUpdate security: - - AnonKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' requestBody: required: true content: application/json: schema: - type: object - required: - - email - properties: - email: - type: string - format: email + $ref: '#/components/schemas/DatabaseUpdateRequest' responses: '200': - description: Generic success message (doesn't reveal if email exists) + description: Update successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - type: object - properties: - message: - type: string - example: If the email exists, a password reset link has been sent + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: post-uuid + title: Updated Title + status: published + updated_at: '2026-01-13T10:05:00Z' + count: 1 + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '403': - description: Password reset is disabled for this project + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - description: Rate limit exceeded (10 requests per hour per IP) + '404': + description: Database not found content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/reset-password: + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + /databases/{databaseName}/query/delete: post: tags: - - Authentication - summary: Reset password with recovery token + - Database Queries + summary: Delete data from database (REST API) description: | - Reset password using recovery token from forgot-password. - Revokes all existing sessions for security. - operationId: authResetPassword + Delete rows from your database using REST API. + + **Safety:** Requires at least one filter to prevent accidental mass deletions + + **Security:** Row-Level Security ensures you can only delete data you have access to + + **Note:** If RLS blocks the delete, an empty result is returned (not an error) + operationId: queryDatabaseDelete security: - - AnonKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' requestBody: required: true content: application/json: schema: - type: object - required: - - token - - new_password - properties: - token: - type: string - description: Recovery token from forgot-password - new_password: - type: string - description: | - Password validated after NFC normalization against the - policy returned by GET /auth/password-policy. + $ref: '#/components/schemas/DatabaseDeleteRequest' responses: '200': - description: Password reset successful + description: Delete successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - type: object - properties: - message: - type: string + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: post-uuid + title: Deleted Post + count: 1 '400': - description: Password doesn't meet requirements + description: Invalid request or missing filters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '401': - description: Invalid or expired token - '503': - description: Compromised-password screening is temporarily unavailable + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/confirm: + '403': + description: Access denied + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Database not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + /databases/{databaseName}/branches/{branchName}/query/ping: post: tags: - - Authentication - summary: Confirm email address + - Database Queries + summary: Database connectivity probe (REST API) description: | - Confirm email address using token sent via email. - Required if require_email_confirmation is enabled. - operationId: authConfirmEmail + Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the + same authentication, status/bandwidth gating, and metering as the other + `/query/*` endpoints. + + Unlike those endpoints, ping takes **no request body** and performs **no + table-name validation**, so it works on any database — including a freshly + provisioned, empty one. It is a real committed round-trip through pgproxy, + so a `200` means the database is reachable and queryable. Used by the + dashboard's database connection test. + + **Branch-targeted.** Runs against the named branch instead of the parent + database, using the branch's own credentials. The branch must be `active` + and unexpired. Nothing about this request can reach the parent's data. + operationId: queryDatabaseBranchPing security: - - AnonKey: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - token - properties: - token: - type: string - description: Confirmation token from email + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/BranchName' responses: '200': - description: Email confirmed or already confirmed + description: Database is reachable + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - type: object - properties: - message: - type: string - enum: - - Email confirmed successfully - - Email already confirmed - examples: - confirmed: - summary: Fresh confirmation - value: - message: Email confirmed successfully - alreadyConfirmed: - summary: Token belongs to already-confirmed user - value: - message: Email already confirmed - '400': - description: Missing confirmation token in request body + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - '?column?': 1 + count: 1 '401': - description: Invalid or expired token - /auth/resend-confirmation: + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Access denied + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Database or branch not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + '503': + $ref: '#/components/responses/DatabaseBranchQueryUnavailable' + /databases/{databaseName}/branches/{branchName}/query/select: post: tags: - - Authentication - summary: Resend confirmation email + - Database Queries + summary: Query database with SELECT (REST API) description: | - Resend email confirmation link. - Returns generic message to prevent email enumeration. - No email is sent when the account does not exist or is already confirmed. - If the account exists and is unconfirmed, a new token is generated and - any previous confirmation token is invalidated. - operationId: authResendConfirmation + Query your database using a simple REST API - no SQL required! + + **Authentication:** Requires auth user access token (from signup/signin) + + **Row-Level Security:** Automatically enforced - you see only data you have access to + + **Use Cases:** + - Query from browser/mobile apps + - Simple data retrieval + - Filtered searches with sorting and pagination + + **Note:** For complex queries (JOINs, CTEs), use a function with direct SQL + + **Branch-targeted.** Runs against the named branch instead of the parent + database, using the branch's own credentials. The branch must be `active` + and unexpired. Nothing about this request can reach the parent's data. + operationId: queryDatabaseBranchSelect security: - - AnonKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/BranchName' requestBody: required: true content: application/json: schema: - type: object - required: - - email - properties: - email: - type: string - format: email + $ref: '#/components/schemas/DatabaseSelectRequest' responses: '200': - description: Generic success message + description: Query successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - type: object - properties: - message: - type: string - '429': - description: Rate limit exceeded + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: uuid-123 + title: My Post + content: Post content + status: published + views: 150 + created_at: '2026-01-13T10:00:00Z' + count: 1 + '400': + description: Invalid query content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/signup-anonymous: - post: - tags: - - Authentication - summary: Create anonymous user - description: | - Create guest user without email/password. - - User metadata (like display_name) can be included and will appear in realtime presence events. - Requires enable_anonymous_signins to be true. - operationId: authSignupAnonymous - security: - - AnonKey: [] - requestBody: - description: Optional user metadata - content: - application/json: - schema: - type: object - properties: - user_metadata: - type: object - additionalProperties: true - description: Custom user metadata (e.g., display_name, avatar_url) - example: - display_name: Alice - avatar_url: https://example.com/alice.jpg - responses: - '201': - description: Anonymous user created + '401': + description: Not authenticated content: application/json: schema: - $ref: '#/components/schemas/AuthTokenResponse' + $ref: '#/components/schemas/Error' '403': - description: Anonymous signins disabled - /auth/user/convert-anonymous: + description: Access denied + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Database or branch not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + '503': + $ref: '#/components/responses/DatabaseBranchQueryUnavailable' + /databases/{databaseName}/branches/{branchName}/query/insert: post: tags: - - Authentication - summary: Convert anonymous user to authenticated + - Database Queries + summary: Insert data into database (REST API) description: | - Add email and password to anonymous user. - Requires auth user access token. - If require_email_confirmation is enabled for the project, the converted - user remains unconfirmed until /auth/confirm succeeds. When email - sending is enabled, a confirmation email is sent during conversion. - operationId: authConvertAnonymous + Insert new rows into your database using REST API. + + **Authentication:** Requires auth user access token + + **Auto-set user_id:** If your table has a trigger using `auth.uid()`, + user_id will be automatically set to the authenticated user + + **Security:** Row-Level Security policies are enforced + + **Branch-targeted.** Runs against the named branch instead of the parent + database, using the branch's own credentials. The branch must be `active` + and unexpired. Nothing about this request can reach the parent's data. + operationId: queryDatabaseBranchInsert security: - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/BranchName' requestBody: required: true content: application/json: schema: - type: object - required: - - email - - password - properties: - email: - type: string - format: email - password: - type: string - description: | - Password validated after NFC normalization against the - policy returned by GET /auth/password-policy. - user_metadata: - type: object - additionalProperties: true + $ref: '#/components/schemas/DatabaseInsertRequest' responses: '200': - description: User converted successfully + description: Insert successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - type: object - properties: - user: - $ref: '#/components/schemas/AuthUser' + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: uuid-123 + title: My New Post + content: This is the content + status: draft + user_id: user-uuid + created_at: '2026-01-13T10:00:00Z' + count: 1 '400': - description: Not an anonymous user + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '403': - description: | - The chosen email domain is not in `allowed_email_domains` - '409': - description: Email already in use - '503': - description: Compromised-password screening is temporarily unavailable + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/user/change-email: + '404': + description: Database or branch not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + '503': + $ref: '#/components/responses/DatabaseBranchQueryUnavailable' + /databases/{databaseName}/branches/{branchName}/query/update: post: tags: - - Authentication - summary: Request email change + - Database Queries + summary: Update data in database (REST API) description: | - Request to change user's email address. - Sends confirmation token to new email address. - operationId: authRequestEmailChange + Update existing rows in your database using REST API. + + **Security:** Row-Level Security ensures you can only update data you have access to + + **Safety:** Requires at least one filter to prevent accidental mass updates. A + request with no `filters` is rejected with `400` (mirrors delete). This matters + for service-key queries, which run with full access and bypass RLS. + + **Note:** If RLS blocks the update, an empty result is returned (not an error) + + **Branch-targeted.** Runs against the named branch instead of the parent + database, using the branch's own credentials. The branch must be `active` + and unexpired. Nothing about this request can reach the parent's data. + operationId: queryDatabaseBranchUpdate security: - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/BranchName' requestBody: required: true content: application/json: schema: - type: object - required: - - new_email - properties: - new_email: - type: string - format: email + $ref: '#/components/schemas/DatabaseUpdateRequest' responses: '200': - description: Confirmation email sent + description: Update successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - type: object - properties: - message: - type: string - new_email: - type: string + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: post-uuid + title: Updated Title + status: published + updated_at: '2026-01-13T10:05:00Z' + count: 1 '400': - description: Invalid email format or same as current email + description: Invalid request content: application/json: schema: @@ -7686,58 +8089,71 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: | - The requested email domain is not in `allowed_email_domains` + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Email already in use + '404': + description: Database or branch not found content: application/json: schema: $ref: '#/components/schemas/Error' '429': - description: Rate limit exceeded (10 requests per hour per IP) - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /auth/user/confirm-email-change: + $ref: '#/components/responses/DatabaseQueryCapExceeded' + '503': + $ref: '#/components/responses/DatabaseBranchQueryUnavailable' + /databases/{databaseName}/branches/{branchName}/query/delete: post: tags: - - Authentication - summary: Confirm email change - description: Confirm email change with token sent to new address - operationId: authConfirmEmailChange + - Database Queries + summary: Delete data from database (REST API) + description: | + Delete rows from your database using REST API. + + **Safety:** Requires at least one filter to prevent accidental mass deletions + + **Security:** Row-Level Security ensures you can only delete data you have access to + + **Note:** If RLS blocks the delete, an empty result is returned (not an error) + + **Branch-targeted.** Runs against the named branch instead of the parent + database, using the branch's own credentials. The branch must be `active` + and unexpired. Nothing about this request can reach the parent's data. + operationId: queryDatabaseBranchDelete security: - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/DatabaseName' + - $ref: '#/components/parameters/BranchName' requestBody: required: true content: application/json: schema: - type: object - required: - - email_change_token - properties: - email_change_token: - type: string + $ref: '#/components/schemas/DatabaseDeleteRequest' responses: '200': - description: Email changed successfully + description: Delete successful + headers: + X-Volcano-Proxy-Ms: + $ref: '#/components/headers/DatabaseQueryProxyMs' + X-Volcano-Proxy-Handler-Ms: + $ref: '#/components/headers/DatabaseQueryProxyHandlerMs' + X-Volcano-Compute-Ms: + $ref: '#/components/headers/DatabaseQueryComputeMs' content: application/json: schema: - type: object - properties: - message: - type: string - user: - $ref: '#/components/schemas/AuthUser' + $ref: '#/components/schemas/DatabaseQueryResult' + example: + data: + - id: post-uuid + title: Deleted Post + count: 1 '400': - description: Invalid or expired token, or no pending email change + description: Invalid request or missing filters content: application/json: schema: @@ -7749,283 +8165,282 @@ paths: schema: $ref: '#/components/schemas/Error' '403': - description: | - The pending email domain is no longer in `allowed_email_domains`. - Re-checked here because the allowlist can narrow between the request - and the confirmation. + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Email is now in use by another user + '404': + description: Database or branch not found content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/user/cancel-email-change: - delete: + '429': + $ref: '#/components/responses/DatabaseQueryCapExceeded' + '503': + $ref: '#/components/responses/DatabaseBranchQueryUnavailable' + /databases/regions: + get: tags: - - Authentication - summary: Cancel pending email change - operationId: authCancelEmailChange - security: - - AuthUserAccessToken: [] + - Databases + summary: List platform-supported regions for database provisioning + operationId: listDatabaseRegions + description: | + Returns the regions enabled for database provisioning in this platform environment. + These are the same regions offered for function deployment, and the only values + the `region` field of a database accepts. + This is a public endpoint that doesn't require authentication. responses: '200': - description: Email change cancelled + description: List of platform-supported regions content: application/json: schema: - type: object - properties: - message: - type: string - '401': - description: Not authenticated + type: array + items: + type: object + properties: + id: + type: string + example: us-east-1 + description: Region identifier for API usage + name: + type: string + example: US East (N. Virginia) + description: Human-readable region location + /databases/postgres-versions: + get: + tags: + - Databases + summary: List available PostgreSQL versions + operationId: listPostgresVersions + description: | + Returns a list of supported PostgreSQL major versions for database provisioning. + This is a public endpoint that doesn't require authentication. + responses: + '200': + description: List of available PostgreSQL versions content: application/json: schema: - $ref: '#/components/schemas/Error' - /auth/user/sessions: + type: array + items: + type: object + properties: + version: + type: string + example: '16' + description: PostgreSQL major version number + name: + type: string + example: PostgreSQL 16 + description: Human-readable version name + default: + type: boolean + description: Whether this is the default version (recommended) + deprecated: + type: boolean + description: Whether this version is deprecated (approaching EOL) + /functions/runtimes: get: tags: - - Authentication - summary: Get current user's sessions + - Functions + summary: List supported function runtimes + operationId: listFunctionRuntimes + security: [] description: | - Returns paginated sessions for the currently authenticated user. - Each session includes device info, IP addresses, and activity timestamps. - The current session is marked with `is_current: true`. - - **Ordering and pagination.** Without `sort`, results are ordered by most - recent activity and paged with `page`/`limit`, returning the - `sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the - legacy default and is preserved for existing clients. - - Send `sort=created_at` to opt into the standard list contract: results are - ordered by session start (newest first) and may be paged either with - `page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded - `offset` past the cursor anchor. Cursor responses use the shared - `data` envelope with `next_cursor`/`prev_cursor`. - - Unlike other list endpoints, sending `limit` without `page` does **not** - select cursor mode here; `sort=created_at` is the only opt-in. Cursor - pagination is rejected with 400 for the activity order, because - `last_activity_at` changes whenever a session refreshes its token: a row - that crosses the cursor anchor between two requests would be skipped and - never shown. The `status=expired` filter is also offset-only because a - session can expire above the cursor anchor during a walk. Sending that - filter in cursor mode, `page` with `cursor` or `ending_before`, or both - cursor directions returns 400. - operationId: authGetMySessions - security: - - AuthUserAccessToken: [] - parameters: - - name: page - in: query - description: Page number (1-indexed) - schema: - type: integer - minimum: 1 - default: 1 - - name: limit - in: query - description: Number of sessions per page (max 100) - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - - name: sort - in: query - description: | - Sort key. `last_activity` (default) orders by most recent activity and - supports offset pagination only. `created_at` orders by session start - and supports both offset and cursor pagination. - schema: - type: string - enum: - - last_activity - - created_at - default: last_activity - - name: status - in: query - description: | - Filter by whether the session can still be refreshed. Omit for every - stored session, including expired ones. `expired` is not supported - with cursor pagination. - schema: - type: string - enum: - - active - - expired - - name: cursor - in: query - description: | - Opaque keyset cursor from a previous response's `next_cursor`. Requires - `sort=created_at`; mutually exclusive with `page` and `ending_before`. - schema: - type: string - - name: ending_before - in: query - description: | - Opaque keyset cursor from a previous response's `prev_cursor`, paging - backward. Requires `sort=created_at`; mutually exclusive with `page` - and `cursor`. - schema: - type: string - - name: offset - in: query - description: | - Bounded number of rows to skip past the cursor anchor (the hybrid - jump, maximum 100000). Ignored unless `cursor` or `ending_before` is - supplied. - schema: - type: integer - minimum: 0 - maximum: 100000 + Returns the public function runtime catalog: every runtime a deploy accepts, its display + label for runtime pickers, language defaults, durable capability, and local source packaging + metadata for deployments. + This is a public endpoint that doesn't require authentication. responses: '200': - description: Paginated list of user sessions - content: - application/json: - schema: - type: object - properties: - sessions: - type: array - items: - $ref: '#/components/schemas/AuthSession' - total: - type: integer - description: Total number of sessions - page: - type: integer - description: Current page number - limit: - type: integer - description: Number of sessions per page - total_pages: - type: integer - description: Total number of pages - data: - type: array - description: Sessions for this page (cursor pagination only) - items: - $ref: '#/components/schemas/AuthSession' - has_more: - type: boolean - description: Whether a further page exists (cursor pagination only) - next_cursor: - type: string - description: Opaque cursor for the next page (cursor pagination only) - prev_cursor: - type: string - description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. - '400': - description: Invalid or conflicting pagination parameters - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + description: Supported function runtimes content: application/json: schema: - $ref: '#/components/schemas/Error' - delete: + $ref: '#/components/schemas/FunctionRuntimesResponse' + /functions/regions: + get: tags: - - Authentication - summary: Sign out from all other devices + - Functions + summary: List available regions for function deployment + operationId: listFunctionRegions + security: [] description: | - Deletes all sessions except the current one. - Use this to log out from all other devices while keeping the current session active. - operationId: authDeleteAllMySessions - security: - - AuthUserAccessToken: [] + Returns the configured regions where functions can be deployed, each annotated + with a human-readable label and country flag emoji for use in UI pickers. + This is a public endpoint that doesn't require authentication. responses: - '204': - description: All other sessions deleted - '401': - description: Not authenticated + '200': + description: Available function deployment regions content: application/json: schema: - $ref: '#/components/schemas/Error' - /auth/user/sessions/{sessionId}: - delete: + type: array + items: + $ref: '#/components/schemas/FunctionRegion' + /projects/{id}/variables/{name}: + get: tags: - - Authentication - summary: Sign out from specific device + - Variables + summary: Get variable by name description: | - Deletes a specific session, logging out that device. - You can get session IDs from the list sessions endpoint. - operationId: authDeleteMySession + Returns a project-level environment variable used by deployed functions and frontends. + operationId: getVariable security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - name: sessionId - in: path - required: true - description: The session ID to delete - schema: - type: string - format: uuid + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/VariableName' responses: - '204': - description: Session deleted - '401': - description: Not authenticated + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/Variable' '404': - description: Session not found + description: Variable not found content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/user: - get: + put: tags: - - Authentication - summary: Get current user profile - description: Returns authenticated user's profile. Requires access token. - operationId: authGetUser + - Variables + summary: Update a variable + description: | + Updates a project-level environment variable and triggers asynchronous propagation + to deployed functions and frontends in the project's configured regions. + operationId: updateVariable security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/VariableName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateVariableRequest' responses: '200': - description: User profile + description: Variable updated content: application/json: schema: - type: object - properties: - user: - $ref: '#/components/schemas/AuthUser' - '401': - description: Not authenticated - access token missing or invalid + $ref: '#/components/schemas/Variable' + '400': + description: Invalid or reserved variable name content: application/json: schema: $ref: '#/components/schemas/Error' - put: + '404': + description: Variable not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Private variable membership writes are disabled during rollout + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: tags: - - Authentication - summary: Update user profile - description: Update password or metadata. Requires access token. - operationId: authUpdateUser + - Variables + summary: Delete a variable + description: | + Deletes a project-level environment variable and triggers asynchronous propagation + of the removal to deployed functions and frontends in the project's configured regions. + operationId: deleteVariable security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/VariableName' + responses: + '204': + description: Variable deleted + '404': + description: Variable not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/password-policy: + get: + tags: + - Authentication + summary: Get the effective password policy + description: | + Returns the backend-enforced password bounds and compromised-password + screening status for the project identified by the anon key. A valid + anon key is required, but no route-specific auth permission is needed. + operationId: authGetPasswordPolicy + security: + - AnonKey: [] + responses: + '200': + description: Effective password policy + content: + application/json: + schema: + $ref: '#/components/schemas/AuthPasswordPolicy' + '401': + description: Invalid, missing, or revoked anon key + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Project or auth configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/signup: + post: + tags: + - Authentication + summary: Sign up a new auth user + description: | + Create a new end-user account. The project is determined from the anon key. + Requires project-specific anon key in Authorization header. + + **Session-less**: signup never issues a session. On success it returns a + uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client + obtains a session with a subsequent `POST /auth/signin`. If email confirmation + is enabled for the project, a confirmation email is sent and + `confirmation_required` is `true`. + + **Anti-enumeration**: a signup for an already-registered email returns the + exact same `201` response as a fresh signup — it never returns `409` — so the + response cannot be used to discover which emails are registered. + operationId: authSignup + security: + - AnonKey: [] requestBody: + required: true content: application/json: schema: type: object + required: + - email + - password properties: + email: + type: string + format: email password: type: string description: | @@ -8034,1177 +8449,1102 @@ paths: user_metadata: type: object additionalProperties: true - description: | - Metadata keys to merge into the current user metadata. - Omitted keys remain unchanged; set a key to null to remove it. - Merging is shallow; nested objects replace the stored value for that top-level key. responses: - '200': - description: Profile updated + '201': + description: | + Signup acknowledged (session-less). Returned identically for a new + account and for an already-registered email (anti-enumeration). content: application/json: schema: - type: object - properties: - user: - $ref: '#/components/schemas/AuthUser' + $ref: '#/components/schemas/AuthSignupResponse' '400': - description: Bad request - invalid password or metadata format - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + description: Invalid input (bad email/password format) '401': - description: Not authenticated - access token missing or invalid - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + description: | + Unauthorized - Invalid, tampered, revoked, or wrong-project anon key + '403': + description: | + Forbidden - Signups disabled, anon key lacks signup permission, or the + email domain is not in `allowed_email_domains`. The internal + `anonymous.volcano.internal` domain is reserved for anonymous + accounts and is refused whatever the project allows. + '429': + description: Rate limit exceeded '503': description: Compromised-password screening is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/user/identities: - get: + /auth/signin: + post: tags: - Authentication - summary: List the current user's identities + summary: Sign in an auth user description: | - Returns every real email identity the account owns. An account can own - multiple identities (for example a password identity plus one or more - OAuth identities on different emails). Anonymous accounts have no real - identity and return an empty list. - operationId: authListIdentities + Authenticate with email and password. Requires an anon key. + + Set `session_mode` to `cookie` to request HttpOnly refresh-token + storage. Cookie mode is honored only for an exact, credentialed CORS + origin on the same schemeful site as this API. Otherwise the response + retains the refresh token in its body. A frontend on its default + Volcano URL is cross-site with this API and so always gets the body + token. + operationId: authSignin security: - - AuthUserAccessToken: [] + - AnonKey: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + - password + properties: + email: + type: string + password: + type: string + session_mode: + type: string + enum: + - cookie responses: '200': - description: List of identities + description: Signin successful content: application/json: schema: - $ref: '#/components/schemas/AuthIdentitiesResponse' + $ref: '#/components/schemas/AuthTokenResponse' + '400': + description: Invalid input (missing email/password) '401': - description: Not authenticated - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /auth/user/identities/{identityId}: - delete: + description: | + Unauthorized - Invalid credentials, invalid/tampered/revoked anon key, + or account banned/deleted + '403': + description: | + Forbidden - Anon key lacks signin permission, or the email domain is + not in `allowed_email_domains` while `allowed_email_domains_mode` is + `signup_and_signin`. The domain is taken from the account's canonical + email (its primary identity), which is not necessarily the address in + the request. + '429': + description: Rate limit exceeded + /auth/refresh: + post: tags: - Authentication - summary: Unlink an identity from the current user + summary: Refresh access token description: | - Removes a non-primary identity and its attached sign-in methods. Refused - when the identity is the account's primary, its only identity, or when - removing it would leave the account with no way to sign in. - operationId: authUnlinkIdentity + Get a new access token using a refresh token. Requires an anon key. + + Send `refresh_token` in the body for the default flow. An eligible + cookie-mode browser request may instead send `session_mode: cookie` + with an empty token or omit the request body; the API reads and resets + the project's HttpOnly cookie and omits `refresh_token` from the + response. + operationId: authRefresh security: - - AuthUserAccessToken: [] - parameters: - - name: identityId - in: path - required: true - description: The identity ID to unlink - schema: - type: string - format: uuid + - AnonKey: [] + requestBody: + required: false + content: + application/json: + schema: + type: object + properties: + refresh_token: + type: string + session_mode: + type: string + enum: + - cookie responses: - '204': - description: Identity unlinked - '400': - description: Identity cannot be unlinked (primary, last, or would remove last sign-in method), or the identity id is malformed + '200': + description: Token refreshed content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/AuthTokenResponse' '401': - description: Not authenticated + description: Invalid or expired refresh token content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Identity not found + '403': + description: | + The account's email domain is not in `allowed_email_domains` while + `allowed_email_domains_mode` is `signup_and_signin`, so the session + cannot be extended content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/user/methods: - get: - tags: - - Authentication - summary: List the current user's sign-in methods - description: | - Returns a flat list of every sign-in method the account owns (password, - each OAuth provider, and any active anonymous method), with the primary - method flagged. Password stubs and converted anonymous methods are excluded. - operationId: authListMethods - security: - - AuthUserAccessToken: [] - responses: - '200': - description: List of sign-in methods - content: - application/json: - schema: - $ref: '#/components/schemas/AuthMethodsResponse' - '401': - description: Not authenticated + '429': + description: Rate limit exceeded content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/user/methods/{methodId}/promote: + /auth/logout: post: tags: - Authentication - summary: Set a method as the account's primary + summary: Logout (revoke refresh token) description: | - Promotes the given method to the account's primary sign-in method. The - account's canonical email is re-derived from the promoted method's identity. - Refused for password stubs and converted anonymous methods, and for an - identity whose domain is outside the project's `allowed_email_domains`. - operationId: authPromoteMethod + Invalidate a refresh token. Requires an anon key. + + Send `refresh_token` for the default flow. An eligible cookie-mode + browser request may instead send `session_mode: cookie` with an empty + token; logout remains idempotent when the cookie is missing or expired. + operationId: authLogout security: - - AuthUserAccessToken: [] - parameters: - - name: methodId - in: path - required: true - description: The method ID to promote - schema: - type: string - format: uuid + - AnonKey: [] + requestBody: + required: false + content: + application/json: + schema: + type: object + properties: + refresh_token: + type: string + session_mode: + type: string + enum: + - cookie + responses: + '204': + description: Logged out successfully + /auth/forgot-password: + post: + tags: + - Authentication + summary: Request password reset + description: | + Generates recovery token and stores it (email sending pending). + Returns generic message to prevent email enumeration. + Project is identified via the anon key. + operationId: authForgotPassword + security: + - AnonKey: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + properties: + email: + type: string + format: email responses: '200': - description: The promoted method - content: - application/json: - schema: - $ref: '#/components/schemas/AuthMethodSummary' - '400': - description: This method cannot be set as primary (password stub, converted anonymous method, or unverified email), or the method id is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + description: Generic success message (doesn't reveal if email exists) content: application/json: schema: - $ref: '#/components/schemas/Error' + type: object + properties: + message: + type: string + example: If the email exists, a password reset link has been sent '403': - description: The promoted identity's email domain is not in the project's allowed_email_domains + description: Password reset is disabled for this project content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Method not found + '429': + description: Rate limit exceeded (10 requests per hour per IP) content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/auth/insights: - get: + /auth/reset-password: + post: tags: - - Auth Admin - summary: Get auth user insights + - Authentication + summary: Reset password with recovery token description: | - Returns current auth-user totals, rolling 30-day active users, and - zero-filled signup and successful sign-in counts for an inclusive UTC - date range. Weeks start on Monday. Sign-in counts and active-user - activity begin when collection is deployed. Historical signup counts - are backfilled from users present at deployment. Token refreshes affect - active users but not the sign-in series. - operationId: getAuthInsights + Reset password using recovery token from forgot-password. + Revokes all existing sessions for security. + operationId: authResetPassword security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: from - in: query - description: Inclusive UTC start date. Defaults to 29 days before `to`. - schema: - type: string - format: date - - name: to - in: query - description: Inclusive UTC end date. Defaults to today. - schema: - type: string - format: date - - name: interval - in: query - description: Chart bucket size. Defaults to `day`. - schema: - $ref: '#/components/schemas/AuthInsightsInterval' + - AnonKey: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - token + - new_password + properties: + token: + type: string + description: Recovery token from forgot-password + new_password: + type: string + description: | + Password validated after NFC normalization against the + policy returned by GET /auth/password-policy. responses: '200': - description: Auth insights retrieved + description: Password reset successful content: application/json: schema: - $ref: '#/components/schemas/AuthInsightsResponse' - example: - project_id: 4f165080-a931-4e03-b3bd-41c45c3f0058 - observed_at: '2026-07-20T18:00:00Z' - window: - from: '2026-06-21' - to: '2026-07-20' - interval: day - summary: - total_users: 1234 - active_users_30d: 418 - series: - - bucket_start: '2026-07-20' - signups: 12 - signins: 97 - is_partial: true + type: object + properties: + message: + type: string '400': - description: Invalid date range or interval - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + description: Password doesn't meet requirements '401': - description: Unauthorized - invalid or missing token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Access denied - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error + description: Invalid or expired token + '503': + description: Compromised-password screening is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/auth/users: - get: + /auth/confirm: + post: tags: - - Auth Admin - summary: List all auth users (admin) - description: List auth users in project. Requires platform token. - operationId: listAuthUsers + - Authentication + summary: Confirm email address + description: | + Confirm email address using token sent via email. + Required if require_email_confirmation is enabled. + operationId: authConfirmEmail security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' - - name: status - in: query - required: false - description: Filter by effective status. `banned` returns only currently-banned users; an expired temporary ban lists as `active`. - schema: - type: string - enum: - - active - - banned + - AnonKey: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - token + properties: + token: + type: string + description: Confirmation token from email responses: '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/PaginatedAuthUsers' - '400': - description: Invalid status or pagination parameters + description: Email confirmed or already confirmed content: application/json: schema: - $ref: '#/components/schemas/Error' - /projects/{id}/auth/users/{userId}: - get: + type: object + properties: + message: + type: string + enum: + - Email confirmed successfully + - Email already confirmed + examples: + confirmed: + summary: Fresh confirmation + value: + message: Email confirmed successfully + alreadyConfirmed: + summary: Token belongs to already-confirmed user + value: + message: Email already confirmed + '400': + description: Missing confirmation token in request body + '401': + description: Invalid or expired token + /auth/resend-confirmation: + post: tags: - - Auth Admin - summary: Get specific auth user (admin) - operationId: getAuthUser + - Authentication + summary: Resend confirmation email + description: | + Resend email confirmation link. + Returns generic message to prevent email enumeration. + No email is sent when the account does not exist or is already confirmed. + If the account exists and is unconfirmed, a new token is generated and + any previous confirmation token is invalidated. + operationId: authResendConfirmation security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: userId - in: path - required: true - schema: - type: string - format: uuid + - AnonKey: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + properties: + email: + type: string + format: email responses: '200': - description: Auth user details + description: Generic success message content: application/json: schema: - $ref: '#/components/schemas/AuthUser' - delete: + type: object + properties: + message: + type: string + '429': + description: Rate limit exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/signup-anonymous: + post: tags: - - Auth Admin - summary: Delete auth user (admin) - description: Soft-deletes user and revokes all sessions - operationId: deleteAuthUser + - Authentication + summary: Create anonymous user + description: | + Create guest user without email/password. + + User metadata (like display_name) can be included and will appear in realtime presence events. + Requires enable_anonymous_signins to be true. + operationId: authSignupAnonymous security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: userId - in: path - required: true - schema: - type: string - format: uuid + - AnonKey: [] + requestBody: + description: Optional user metadata + content: + application/json: + schema: + type: object + properties: + user_metadata: + type: object + additionalProperties: true + description: Custom user metadata (e.g., display_name, avatar_url) + example: + display_name: Alice + avatar_url: https://example.com/alice.jpg responses: - '204': - description: User deleted - /projects/{id}/auth/users/{userId}/sessions: - get: + '201': + description: Anonymous user created + content: + application/json: + schema: + $ref: '#/components/schemas/AuthTokenResponse' + '403': + description: Anonymous signins disabled + /auth/user/convert-anonymous: + post: tags: - - Auth Admin - summary: List user sessions + - Authentication + summary: Convert anonymous user to authenticated description: | - List paginated sessions for a specific auth user. - Returns session details including device info, IP address, and activity timestamps. - - Ordering and pagination match `GET /auth/user/sessions`: the default is - activity order with `page`/`limit` and the legacy `sessions` body, and - `sort=created_at` opts into the standard cursor/offset hybrid with the - shared `data` envelope. Cursor pagination is only available for - `sort=created_at`, because the activity timestamp changes under paging. - The `status=expired` filter is offset-only because sessions can expire - above a cursor anchor during a walk. - operationId: listUserSessions + Add email and password to anonymous user. + Requires auth user access token. + If require_email_confirmation is enabled for the project, the converted + user remains unconfirmed until /auth/confirm succeeds. When email + sending is enabled, a confirmation email is sent during conversion. + operationId: authConvertAnonymous security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: userId - in: path - required: true - schema: - type: string - format: uuid - - name: page - in: query - description: Page number (1-indexed) - schema: - type: integer - minimum: 1 - default: 1 - - name: limit - in: query - description: Number of sessions per page (max 100) - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - - name: sort - in: query - description: | - Sort key. `last_activity` (default) orders by most recent activity and - supports offset pagination only. `created_at` orders by session start - and supports both offset and cursor pagination. - schema: - type: string - enum: - - last_activity - - created_at - default: last_activity - - name: status - in: query - description: | - Filter by whether the session can still be refreshed. Omit for every - stored session, including expired ones. `expired` is not supported - with cursor pagination. - schema: - type: string - enum: - - active - - expired - - name: cursor - in: query - description: | - Opaque keyset cursor from a previous response's `next_cursor`. Requires - `sort=created_at`; mutually exclusive with `page` and `ending_before`. - schema: - type: string - - name: ending_before - in: query - description: | - Opaque keyset cursor from a previous response's `prev_cursor`, paging - backward. Requires `sort=created_at`; mutually exclusive with `page` - and `cursor`. - schema: - type: string - - name: offset - in: query - description: | - Bounded number of rows to skip past the cursor anchor (the hybrid - jump, maximum 100000). Ignored unless `cursor` or `ending_before` is - supplied. - schema: - type: integer - minimum: 0 - maximum: 100000 + - AuthUserAccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + - password + properties: + email: + type: string + format: email + password: + type: string + description: | + Password validated after NFC normalization against the + policy returned by GET /auth/password-policy. + user_metadata: + type: object + additionalProperties: true responses: '200': - description: Paginated list of user sessions + description: User converted successfully content: application/json: schema: type: object properties: - sessions: - type: array - items: - $ref: '#/components/schemas/AuthSession' - total: - type: integer - description: Total number of sessions - page: - type: integer - description: Current page number - limit: - type: integer - description: Number of sessions per page - total_pages: - type: integer - description: Total number of pages - data: - type: array - description: Sessions for this page (cursor pagination only) - items: - $ref: '#/components/schemas/AuthSession' - has_more: - type: boolean - description: Whether a further page exists (cursor pagination only) - next_cursor: - type: string - description: Opaque cursor for the next page (cursor pagination only) - prev_cursor: - type: string - description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. + user: + $ref: '#/components/schemas/AuthUser' '400': - description: Invalid or conflicting pagination parameters + description: Not an anonymous user + '403': + description: | + The chosen email domain is not in `allowed_email_domains` + '409': + description: Email already in use + '503': + description: Compromised-password screening is temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: User not found - delete: - tags: - - Auth Admin - summary: Delete all user sessions - description: | - Revokes all sessions for a user, forcing them to re-authenticate on all devices. - Use this to log out a user from everywhere. - operationId: deleteAllUserSessions - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - '204': - description: All sessions deleted - '404': - description: User not found - /projects/{id}/auth/users/{userId}/sessions/{sessionId}: - delete: - tags: - - Auth Admin - summary: Delete specific session - description: | - Revokes a specific session for a user. - Use this to log out a user from a single device. - operationId: deleteUserSession - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: userId - in: path - required: true - schema: - type: string - format: uuid - - name: sessionId - in: path - required: true - schema: - type: string - format: uuid - responses: - '204': - description: Session deleted - '404': - description: Session or user not found - /projects/{id}/auth/users/{userId}/ban: + /auth/user/change-email: post: tags: - - Auth Admin - summary: Ban a user + - Authentication + summary: Request email change description: | - Bans a user temporarily or permanently. Banned users cannot sign in - and all their active sessions are immediately revoked. - - - Omit `banned_until` for a permanent ban - - Provide `banned_until` ISO timestamp for a temporary ban - operationId: banAuthUser + Request to change user's email address. + Sends confirmation token to new email address. + operationId: authRequestEmailChange security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: userId - in: path - required: true - schema: - type: string - format: uuid + - AuthUserAccessToken: [] requestBody: + required: true content: application/json: schema: type: object + required: + - new_email properties: - banned_until: + new_email: type: string - format: date-time - description: When the ban expires (omit for permanent ban) - example: '2026-12-31T23:59:59Z' + format: email responses: '200': - description: User banned successfully + description: Confirmation email sent content: application/json: schema: - $ref: '#/components/schemas/BanUserResponse' - '404': - description: User not found + type: object + properties: + message: + type: string + new_email: + type: string + '400': + description: Invalid email format or same as current email content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/auth/users/{userId}/unban: - post: - tags: - - Auth Admin - summary: Unban a user - description: | - Removes a ban from a user, restoring their ability to sign in. - The user's status is set back to 'active'. - operationId: unbanAuthUser - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - '200': - description: User unbanned successfully + '401': + description: Not authenticated content: application/json: schema: - $ref: '#/components/schemas/UnbanUserResponse' - '404': - description: User not found + $ref: '#/components/schemas/Error' + '403': + description: | + The requested email domain is not in `allowed_email_domains` content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/email-templates: - get: - tags: - - Auth Configuration - summary: List email templates - description: Returns all custom email templates for this project. - operationId: listEmailTemplates - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - responses: - '200': - description: Email templates list + '409': + description: Email already in use content: application/json: schema: - type: object - properties: - data: - type: array - items: - $ref: '#/components/schemas/EmailTemplate' + $ref: '#/components/schemas/Error' + '429': + description: Rate limit exceeded (10 requests per hour per IP) + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/user/confirm-email-change: post: tags: - - Auth Configuration - summary: Create email template - description: | - Creates a custom email template for the project. Custom email templates - are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are - rejected with 403, and HOBBY projects always send the built-in default - templates regardless of any previously saved custom rows. - Every project is created with one template per type, so customizing one - is usually a PUT; creating a type the project already has returns 409. - Valid template types: welcome, confirmation, password_reset, password_changed - operationId: createEmailTemplate + - Authentication + summary: Confirm email change + description: Confirm email change with token sent to new address + operationId: authConfirmEmailChange security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - AuthUserAccessToken: [] requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/CreateEmailTemplateRequest' + type: object + required: + - email_change_token + properties: + email_change_token: + type: string responses: - '201': - description: Template created + '200': + description: Email changed successfully content: application/json: schema: - $ref: '#/components/schemas/EmailTemplate' + type: object + properties: + message: + type: string + user: + $ref: '#/components/schemas/AuthUser' '400': - description: Invalid template type + description: Invalid or expired token, or no pending email change + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Custom email templates require the SUPERAGENT plan + description: | + The pending email domain is no longer in `allowed_email_domains`. + Re-checked here because the allowlist can narrow between the request + and the confirmation. content: application/json: schema: $ref: '#/components/schemas/Error' '409': - description: The project already has a template of this type + description: Email is now in use by another user content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/email-templates/{type}: - get: + /auth/user/cancel-email-change: + delete: tags: - - Auth Configuration - summary: Get email template - operationId: getEmailTemplate + - Authentication + summary: Cancel pending email change + operationId: authCancelEmailChange security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: type - in: path - required: true - schema: - type: string - enum: - - welcome - - confirmation - - password_reset - - password_changed + - AuthUserAccessToken: [] responses: '200': - description: Email template + description: Email change cancelled content: application/json: schema: - $ref: '#/components/schemas/EmailTemplate' - '404': - description: Template not found - put: + type: object + properties: + message: + type: string + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/user/sessions: + get: tags: - - Auth Configuration - summary: Update email template + - Authentication + summary: Get current user's sessions description: | - Updates a custom email template. Custom email templates are a SUPERAGENT-plan - feature: requests from a HOBBY-plan project owner are rejected with 403 - (including after a SUPERAGENT→HOBBY downgrade), so a HOBBY project cannot modify - templates and always sends the built-in defaults. - operationId: updateEmailTemplate + Returns paginated sessions for the currently authenticated user. + Each session includes device info, IP addresses, and activity timestamps. + The current session is marked with `is_current: true`. + + **Ordering and pagination.** Without `sort`, results are ordered by most + recent activity and paged with `page`/`limit`, returning the + `sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the + legacy default and is preserved for existing clients. + + Send `sort=created_at` to opt into the standard list contract: results are + ordered by session start (newest first) and may be paged either with + `page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded + `offset` past the cursor anchor. Cursor responses use the shared + `data` envelope with `next_cursor`/`prev_cursor`. + + Unlike other list endpoints, sending `limit` without `page` does **not** + select cursor mode here; `sort=created_at` is the only opt-in. Cursor + pagination is rejected with 400 for the activity order, because + `last_activity_at` changes whenever a session refreshes its token: a row + that crosses the cursor anchor between two requests would be skipped and + never shown. The `status=expired` filter is also offset-only because a + session can expire above the cursor anchor during a walk. Sending that + filter in cursor mode, `page` with `cursor` or `ending_before`, or both + cursor directions returns 400. + operationId: authGetMySessions security: - - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - - name: type - in: path - required: true + - name: page + in: query + description: Page number (1-indexed) + schema: + type: integer + minimum: 1 + default: 1 + - name: limit + in: query + description: Number of sessions per page (max 100) + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: sort + in: query + description: | + Sort key. `last_activity` (default) orders by most recent activity and + supports offset pagination only. `created_at` orders by session start + and supports both offset and cursor pagination. schema: type: string enum: - - welcome - - confirmation - - password_reset - - password_changed - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateEmailTemplateRequest' + - last_activity + - created_at + default: last_activity + - name: status + in: query + description: | + Filter by whether the session can still be refreshed. Omit for every + stored session, including expired ones. `expired` is not supported + with cursor pagination. + schema: + type: string + enum: + - active + - expired + - name: cursor + in: query + description: | + Opaque keyset cursor from a previous response's `next_cursor`. Requires + `sort=created_at`; mutually exclusive with `page` and `ending_before`. + schema: + type: string + - name: ending_before + in: query + description: | + Opaque keyset cursor from a previous response's `prev_cursor`, paging + backward. Requires `sort=created_at`; mutually exclusive with `page` + and `cursor`. + schema: + type: string + - name: offset + in: query + description: | + Bounded number of rows to skip past the cursor anchor (the hybrid + jump, maximum 100000). Ignored unless `cursor` or `ending_before` is + supplied. + schema: + type: integer + minimum: 0 + maximum: 100000 responses: '200': - description: Template updated + description: Paginated list of user sessions content: application/json: schema: - $ref: '#/components/schemas/EmailTemplate' - '403': - description: Custom email templates require the SUPERAGENT plan + type: object + properties: + sessions: + type: array + items: + $ref: '#/components/schemas/AuthSession' + total: + type: integer + description: Total number of sessions + page: + type: integer + description: Current page number + limit: + type: integer + description: Number of sessions per page + total_pages: + type: integer + description: Total number of pages + data: + type: array + description: Sessions for this page (cursor pagination only) + items: + $ref: '#/components/schemas/AuthSession' + has_more: + type: boolean + description: Whether a further page exists (cursor pagination only) + next_cursor: + type: string + description: Opaque cursor for the next page (cursor pagination only) + prev_cursor: + type: string + description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. + '400': + description: Invalid or conflicting pagination parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Template not found delete: tags: - - Auth Configuration - summary: Delete email template + - Authentication + summary: Sign out from all other devices description: | - Deletes a custom template, reverting to the default. Custom email - templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner - are rejected with 403. - operationId: deleteEmailTemplate + Deletes all sessions except the current one. + Use this to log out from all other devices while keeping the current session active. + operationId: authDeleteAllMySessions security: - - UserToken: [] + - AuthUserAccessToken: [] + responses: + '204': + description: All other sessions deleted + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/user/sessions/{sessionId}: + delete: + tags: + - Authentication + summary: Sign out from specific device + description: | + Deletes a specific session, logging out that device. + You can get session IDs from the list sessions endpoint. + operationId: authDeleteMySession + security: + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - - name: type + - name: sessionId in: path required: true + description: The session ID to delete schema: type: string - enum: - - welcome - - confirmation - - password_reset - - password_changed + format: uuid responses: '204': - description: Template deleted - '403': - description: Custom email templates require the SUPERAGENT plan + description: Session deleted + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Template not found - /email-templates/defaults: + description: Session not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/user: get: tags: - - Auth Configuration - summary: Get default email templates - description: Returns the default email templates used when no custom template is configured. - operationId: getDefaultEmailTemplates + - Authentication + summary: Get current user profile + description: Returns authenticated user's profile. Requires access token. + operationId: authGetUser + security: + - AuthUserAccessToken: [] responses: '200': - description: Default templates + description: User profile content: application/json: schema: type: object properties: - data: - type: array - items: - $ref: '#/components/schemas/EmailTemplate' - /email-templates/defaults/{type}: - get: - tags: - - Auth Configuration - summary: Get default email template by type - operationId: getDefaultEmailTemplate - parameters: - - name: type - in: path - required: true - schema: - type: string - enum: - - welcome - - confirmation - - password_reset - - password_changed - responses: - '200': - description: Default template - content: - application/json: - schema: - $ref: '#/components/schemas/EmailTemplate' - '404': - description: Template type not found - /projects/{id}/auth/config: - get: - tags: - - Auth Configuration - summary: Get auth configuration - operationId: getAuthConfig - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - responses: - '200': - description: Auth configuration + user: + $ref: '#/components/schemas/AuthUser' + '401': + description: Not authenticated - access token missing or invalid content: application/json: schema: - $ref: '#/components/schemas/AuthConfig' + $ref: '#/components/schemas/Error' put: tags: - - Auth Configuration - summary: Update auth configuration - description: | - Updates the project's auth configuration. Only the fields present in - the body are changed. - operationId: updateAuthConfig + - Authentication + summary: Update user profile + description: Update password or metadata. Requires access token. + operationId: authUpdateUser security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - AuthUserAccessToken: [] requestBody: content: application/json: schema: - $ref: '#/components/schemas/UpdateAuthConfigRequest' + type: object + properties: + password: + type: string + description: | + Password validated after NFC normalization against the + policy returned by GET /auth/password-policy. + user_metadata: + type: object + additionalProperties: true + description: | + Metadata keys to merge into the current user metadata. + Omitted keys remain unchanged; set a key to null to remove it. + Merging is shallow; nested objects replace the stored value for that top-level key. responses: '200': - description: Configuration updated + description: Profile updated content: application/json: schema: - $ref: '#/components/schemas/AuthConfig' - '403': - description: | - The update would turn on, widen, or otherwise edit the email domain - allowlist (`allowed_email_domains`, `allowed_email_domains_mode`) - for a project that is not on the SUPERAGENT plan. A HOBBY project keeps - whatever allowlist it already has — parked, enforcing nothing until - it upgrades — and may still remove it, so a downgrade never leaves a - project locked out of its own signups. + type: object + properties: + user: + $ref: '#/components/schemas/AuthUser' + '400': + description: Bad request - invalid password or metadata format content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/auth/config/test-email: - post: - tags: - - Auth Configuration - summary: Send a test email using the project's saved SMTP config - description: | - Sends a diagnostic email to `to_email` using the project's - persisted `auth_config` SMTP credentials. If `html_body` or - `text_body` is supplied, the override path is taken: those - values (plus optional `subject`) are rendered through - html/text templates against the project's `Data` and - used as the body — used by the template editor's "Send Test" - affordance to preview an unsaved template. With both bodies - omitted, a hardcoded diagnostic message is sent and any - `subject` field is ignored. Sending `subject` alone (no - bodies) is rejected with 400 to avoid a silently-dropped - subject or a blank message. Also rejects with 400 if - `email_enabled=false` or `smtp_host` is empty. - operationId: testEmailConfig - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TestEmailRequest' - responses: - '200': - description: Test email sent + '401': + description: Not authenticated - access token missing or invalid content: application/json: schema: - $ref: '#/components/schemas/TestEmailResponse' - '400': - description: Invalid request or email delivery not configured - '401': - description: Unauthorized - '403': - description: Forbidden - '404': - description: Project not found - '502': - description: Template render failure or SMTP delivery failed - /projects/{id}/auth/hosted-pages/{pageType}: + $ref: '#/components/schemas/Error' + '503': + description: Compromised-password screening is temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/user/identities: get: tags: - - Auth Configuration - summary: Get hosted auth page + - Authentication + summary: List the current user's identities description: | - Returns the saved HTML/CSS for the page type, or `page: null` when the - project has not customized it yet. Always returns `defaults` (the theme - shell to seed an editor with, which is valid input to the update endpoint) - and `runtime` (the script the rendered page runs, plus a preview harness). - operationId: getAuthHostedPage + Returns every real email identity the account owns. An account can own + multiple identities (for example a password identity plus one or more + OAuth identities on different emails). Anonymous accounts have no real + identity and return an empty list. + operationId: authListIdentities security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: pageType - in: path - required: true - schema: - $ref: '#/components/schemas/HostedAuthPageType' + - AuthUserAccessToken: [] responses: '200': - description: Hosted page loaded + description: List of identities content: application/json: schema: - $ref: '#/components/schemas/AuthHostedPageResponse' - put: + $ref: '#/components/schemas/AuthIdentitiesResponse' + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/user/identities/{identityId}: + delete: tags: - - Auth Configuration - summary: Update hosted auth page + - Authentication + summary: Unlink an identity from the current user description: | - Saves the current HTML/CSS for this page type. - Security validation rejects script tags, javascript: URLs, inline event handlers, iframe/object/embed/meta/link tags in HTML, - and closing style/head tags in CSS. - operationId: updateAuthHostedPage + Removes a non-primary identity and its attached sign-in methods. Refused + when the identity is the account's primary, its only identity, or when + removing it would leave the account with no way to sign in. + operationId: authUnlinkIdentity security: - - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - - name: pageType + - name: identityId in: path required: true + description: The identity ID to unlink schema: - $ref: '#/components/schemas/HostedAuthPageType' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateAuthHostedPageRequest' + type: string + format: uuid responses: - '200': - description: Hosted page updated + '204': + description: Identity unlinked + '400': + description: Identity cannot be unlinked (primary, last, or would remove last sign-in method), or the identity id is malformed content: application/json: schema: - $ref: '#/components/schemas/AuthHostedPageResponse' - '400': - description: Invalid input or unsafe markup + $ref: '#/components/schemas/Error' '401': - description: Unauthorized - '403': - description: Forbidden + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Project not found - /projects/{id}/auth/pages/appearance: + description: Identity not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /auth/user/methods: get: tags: - - Auth Configuration - summary: Get managed auth page appearance - operationId: getAuthPageAppearance + - Authentication + summary: List the current user's sign-in methods + description: | + Returns a flat list of every sign-in method the account owns (password, + each OAuth provider, and any active anonymous method), with the primary + method flagged. Password stubs and converted anonymous methods are excluded. + operationId: authListMethods security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - AuthUserAccessToken: [] responses: '200': - description: Saved appearance and effective plan state + description: List of sign-in methods content: application/json: schema: - $ref: '#/components/schemas/AuthPageAppearanceResponse' + $ref: '#/components/schemas/AuthMethodsResponse' '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Access denied + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Project not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Appearance could not be read - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /projects/{id}/auth/pages/theme: - put: + /auth/user/methods/{methodId}/promote: + post: tags: - - Auth Configuration - summary: Save the managed auth page theme - operationId: updateAuthPageTheme + - Authentication + summary: Set a method as the account's primary + description: | + Promotes the given method to the account's primary sign-in method. The + account's canonical email is re-derived from the promoted method's identity. + Refused for password stubs and converted anonymous methods, and for an + identity whose domain is outside the project's `allowed_email_domains`. + operationId: authPromoteMethod security: - - UserToken: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateAuthPageThemeRequest' + - name: methodId + in: path + required: true + description: The method ID to promote + schema: + type: string + format: uuid responses: '200': - description: Theme saved + description: The promoted method content: application/json: schema: - $ref: '#/components/schemas/UpdateAuthPageThemeRequest' + $ref: '#/components/schemas/AuthMethodSummary' '400': - description: Invalid or unreadable theme + description: This method cannot be set as primary (password stub, converted anonymous method, or unverified email), or the method id is malformed content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Unauthorized + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Plan does not permit customisation + description: The promoted identity's email domain is not in the project's allowed_email_domains content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: Project not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Theme could not be saved + description: Method not found content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /projects/{id}/auth/insights: + get: tags: - - Auth Configuration - summary: Clear the managed auth page theme - operationId: deleteAuthPageTheme + - Auth Admin + summary: Get auth user insights + description: | + Returns current auth-user totals, rolling 30-day active users, and + zero-filled signup and successful sign-in counts for an inclusive UTC + date range. Weeks start on Monday. Sign-in counts and active-user + activity begin when collection is deployed. Historical signup counts + are backfilled from users present at deployment. Token refreshes affect + active users but not the sign-in series. + operationId: getAuthInsights security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - responses: - '204': - description: Theme cleared - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Plan does not permit customisation - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Theme could not be cleared - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /projects/{id}/auth/pages/{pageType}/layout: - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: pageType - in: path - required: true - schema: - $ref: '#/components/schemas/HostedAuthPageType' - put: - tags: - - Auth Configuration - summary: Save one managed auth page layout - operationId: updateAuthPageLayout - security: - - UserToken: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateAuthPageLayoutRequest' + - name: from + in: query + description: Inclusive UTC start date. Defaults to 29 days before `to`. + schema: + type: string + format: date + - name: to + in: query + description: Inclusive UTC end date. Defaults to today. + schema: + type: string + format: date + - name: interval + in: query + description: Chart bucket size. Defaults to `day`. + schema: + $ref: '#/components/schemas/AuthInsightsInterval' responses: '200': - description: Layout saved + description: Auth insights retrieved content: application/json: schema: - $ref: '#/components/schemas/UpdateAuthPageLayoutRequest' + $ref: '#/components/schemas/AuthInsightsResponse' + example: + project_id: 4f165080-a931-4e03-b3bd-41c45c3f0058 + observed_at: '2026-07-20T18:00:00Z' + window: + from: '2026-06-21' + to: '2026-07-20' + interval: day + summary: + total_users: 1234 + active_users_30d: 418 + series: + - bucket_start: '2026-07-20' + signups: 12 + signins: 97 + is_partial: true '400': - description: Invalid page type or layout + description: Invalid date range or interval content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Unauthorized + description: Unauthorized - invalid or missing token content: application/json: schema: $ref: '#/components/schemas/Error' '403': - description: Plan does not permit customisation + description: Access denied content: application/json: schema: @@ -9216,445 +9556,407 @@ paths: schema: $ref: '#/components/schemas/Error' '500': - description: Layout could not be saved + description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /projects/{id}/auth/users: + get: tags: - - Auth Configuration - summary: Clear one managed auth page layout - operationId: deleteAuthPageLayout + - Auth Admin + summary: List all auth users (admin) + description: List auth users in project. Requires platform token. + operationId: listAuthUsers security: - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + - name: status + in: query + required: false + description: Filter by effective status. `banned` returns only currently-banned users; an expired temporary ban lists as `active`. + schema: + type: string + enum: + - active + - banned responses: - '204': - description: Layout cleared - '400': - description: Invalid page type - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Plan does not permit customisation - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project not found + '200': + description: Successful response content: application/json: schema: - $ref: '#/components/schemas/Error' - '500': - description: Layout could not be cleared + $ref: '#/components/schemas/PaginatedAuthUsers' + '400': + description: Invalid status or pagination parameters content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/auth/pages/{pageType}/preview: + /projects/{id}/auth/users/{userId}: get: tags: - - Auth Configuration - summary: Render a short-lived managed auth page preview - description: | - Public HTML endpoint for a preview URL returned by the POST operation. - The signed ticket contains the unsaved appearance, expires shortly, and - runs the production page runtime against mocked authentication responses. - operationId: renderAuthPagePreview - security: [] + - Auth Admin + summary: Get specific auth user (admin) + operationId: getAuthUser + security: + - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: pageType + - name: userId in: path required: true - schema: - $ref: '#/components/schemas/HostedAuthPageType' - - name: ticket - in: query - required: true schema: type: string - minLength: 1 - maxLength: 4096 - description: Short-lived signed preview ticket returned by the POST operation. + format: uuid responses: '200': - description: Rendered preview document + description: Auth user details content: - text/html: + application/json: schema: - type: string - '404': - description: Ticket is invalid or expired, its path does not match, or managed authentication is disabled - content: - text/plain: - schema: - type: string - '500': - description: Preview could not be rendered - content: - text/plain: - schema: - type: string - post: + $ref: '#/components/schemas/AuthUser' + delete: tags: - - Auth Configuration - summary: Preview an unsaved managed auth page appearance - operationId: previewAuthPage + - Auth Admin + summary: Delete auth user (admin) + description: Soft-deletes user and revokes all sessions + operationId: deleteAuthUser security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: pageType + - name: userId in: path required: true schema: - $ref: '#/components/schemas/HostedAuthPageType' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PreviewAuthPageRequest' + type: string + format: uuid responses: - '200': - description: Short-lived URL for the rendered preview document - content: - application/json: - schema: - $ref: '#/components/schemas/PreviewAuthPageResponse' - '400': - description: Invalid page type or draft - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: Access denied - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project not found or managed authentication is disabled - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Preview could not be rendered - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /projects/{id}/auth/hosted/{pageType}: + '204': + description: User deleted + /projects/{id}/auth/users/{userId}/sessions: get: tags: - - Auth Configuration - summary: Render a managed auth page + - Auth Admin + summary: List user sessions description: | - Public HTML endpoint for signup, forgot-password, device approval, - verify-email, and reset-password pages. Login uses the path without a - page type. - Requires `Accept: text/html`. - Returns 404 when managed hosted pages are disabled for the project. - security: [] - operationId: renderManagedAuthPage + List paginated sessions for a specific auth user. + Returns session details including device info, IP address, and activity timestamps. + + Ordering and pagination match `GET /auth/user/sessions`: the default is + activity order with `page`/`limit` and the legacy `sessions` body, and + `sort=created_at` opts into the standard cursor/offset hybrid with the + shared `data` envelope. Cursor pagination is only available for + `sort=created_at`, because the activity timestamp changes under paging. + The `status=expired` filter is offset-only because sessions can expire + above a cursor anchor during a walk. + operationId: listUserSessions + security: + - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: pageType + - name: userId in: path required: true schema: - $ref: '#/components/schemas/HostedRenderablePageType' - responses: - '200': - description: Hosted auth page HTML - content: - text/html: - schema: - type: string - '400': - description: Invalid project id or unsupported Accept header - '404': - description: Managed pages disabled or page type not found - /projects/{id}/auth/hosted: - get: - tags: - - Auth Configuration - summary: Render default managed auth page - description: | - Public HTML endpoint for the managed login page. - Requires `Accept: text/html`. - security: [] - operationId: renderDefaultManagedAuthPage - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: action + type: string + format: uuid + - name: page in: query - required: false + description: Page number (1-indexed) + schema: + type: integer + minimum: 1 + default: 1 + - name: limit + in: query + description: Number of sessions per page (max 100) + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: sort + in: query + description: | + Sort key. `last_activity` (default) orders by most recent activity and + supports offset pagination only. `created_at` orders by session start + and supports both offset and cursor pagination. schema: type: string enum: - - login - - signup - - forgot-password - - device - description: | - Optional deep-link action for the unified hosted page. Ignored when a - custom login page is configured. `action=device` renders the device - authorization approval UI inline (no redirect to any external app); - it signs the user in and calls `POST /auth/device/verify`. - - name: user_code + - last_activity + - created_at + default: last_activity + - name: status in: query - required: false + description: | + Filter by whether the session can still be refreshed. Omit for every + stored session, including expired ones. `expired` is not supported + with cursor pagination. schema: type: string - description: Device user code (from `POST /auth/device/authorize`) used with `action=device`. - - name: anon_key + enum: + - active + - expired + - name: cursor in: query - required: false + description: | + Opaque keyset cursor from a previous response's `next_cursor`. Requires + `sort=created_at`; mutually exclusive with `page` and `ending_before`. schema: type: string - description: Project anon key used by built-in managed auth flows (required for login/signup/device actions). - - name: state + - name: ending_before in: query - required: false + description: | + Opaque keyset cursor from a previous response's `prev_cursor`, paging + backward. Requires `sort=created_at`; mutually exclusive with `page` + and `cursor`. schema: type: string + - name: offset + in: query description: | - Opaque one-time nonce generated by the client SDK before redirecting - here. On successful login/signup it is echoed back in the post-auth - redirect fragment as `state`, so the SDK can bind the returned session - to the flow it initiated (login-CSRF / session-fixation defense). The - SDK rejects a returned session whose `state` does not match. + Bounded number of rows to skip past the cursor anchor (the hybrid + jump, maximum 100000). Ignored unless `cursor` or `ending_before` is + supplied. + schema: + type: integer + minimum: 0 + maximum: 100000 responses: '200': - description: Hosted auth page HTML + description: Paginated list of user sessions content: - text/html: + application/json: schema: - type: string + type: object + properties: + sessions: + type: array + items: + $ref: '#/components/schemas/AuthSession' + total: + type: integer + description: Total number of sessions + page: + type: integer + description: Current page number + limit: + type: integer + description: Number of sessions per page + total_pages: + type: integer + description: Total number of pages + data: + type: array + description: Sessions for this page (cursor pagination only) + items: + $ref: '#/components/schemas/AuthSession' + has_more: + type: boolean + description: Whether a further page exists (cursor pagination only) + next_cursor: + type: string + description: Opaque cursor for the next page (cursor pagination only) + prev_cursor: + type: string + description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. '400': - description: Invalid project id or unsupported Accept header + description: Invalid or conflicting pagination parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Managed pages disabled - /projects/{id}/auth/hosted/login/options: - get: + description: User not found + delete: tags: - - Auth Configuration - summary: Get hosted login runtime options + - Auth Admin + summary: Delete all user sessions description: | - Returns runtime options for the built-in managed login flow. - Requires `anon_key` query parameter. - Rate limited per project and client IP. Excess requests return `429` and `Retry-After`. - security: [] - operationId: getHostedLoginOptions - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: anon_key - in: query + Revokes all sessions for a user, forcing them to re-authenticate on all devices. + Use this to log out a user from everywhere. + operationId: deleteAllUserSessions + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: userId + in: path required: true schema: type: string + format: uuid responses: - '200': - description: Hosted login options returned - content: - application/json: - schema: - $ref: '#/components/schemas/HostedLoginOptionsResponse' - '401': - description: Invalid or missing anon key + '204': + description: All sessions deleted '404': - description: Managed pages disabled - '429': - description: Rate limit exceeded - /projects/{id}/auth/hosted/login/check-email: + description: User not found + /projects/{id}/auth/users/{userId}/sessions/{sessionId}: + delete: + tags: + - Auth Admin + summary: Delete specific session + description: | + Revokes a specific session for a user. + Use this to log out a user from a single device. + operationId: deleteUserSession + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: userId + in: path + required: true + schema: + type: string + format: uuid + - name: sessionId + in: path + required: true + schema: + type: string + format: uuid + responses: + '204': + description: Session deleted + '404': + description: Session or user not found + /projects/{id}/auth/users/{userId}/ban: post: tags: - - Auth Configuration - summary: Check whether email exists for hosted login flow + - Auth Admin + summary: Ban a user description: | - Used by the built-in managed login page to branch UI between signin and signup. - Requires anon key in Authorization header. - Rate limited per project and client IP. Excess requests return `429` and `Retry-After`. - security: [] - operationId: hostedLoginCheckEmail + Bans a user temporarily or permanently. Banned users cannot sign in + and all their active sessions are immediately revoked. + + - Omit `banned_until` for a permanent ban + - Provide `banned_until` ISO timestamp for a temporary ban + operationId: banAuthUser + security: + - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: Authorization - in: header + - name: userId + in: path required: true schema: type: string - description: Bearer anon key (`Bearer `) + format: uuid requestBody: - required: true content: application/json: schema: - $ref: '#/components/schemas/HostedLoginEmailCheckRequest' + type: object + properties: + banned_until: + type: string + format: date-time + description: When the ban expires (omit for permanent ban) + example: '2026-12-31T23:59:59Z' responses: '200': - description: Email existence evaluated + description: User banned successfully content: application/json: schema: - $ref: '#/components/schemas/HostedLoginEmailCheckResponse' - '401': - description: Invalid or missing anon key - '429': - description: Rate limit exceeded - /projects/{id}/auth/methods: - get: - tags: - - Auth Configuration - summary: Get all authentication methods - description: | - Returns all configured authentication methods for this project, - including email/password, anonymous, device authorization, and OAuth providers. - operationId: getAuthMethods - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - responses: - '200': - description: Authentication methods configuration + $ref: '#/components/schemas/BanUserResponse' + '404': + description: User not found content: application/json: schema: - type: object - properties: - email_password: - type: object - properties: - enabled: - type: boolean - method: - type: string - name: - type: string - anonymous: - type: object - properties: - enabled: - type: boolean - method: - type: string - name: - type: string - oauth_providers: - type: array - items: - type: object - properties: - enabled: - type: boolean - method: - type: string - provider: - type: string - name: - type: string - redirect_url: - type: string - scopes: - type: array - items: - type: string - available_methods: - type: array - items: - type: string - example: - - email_password - - oauth_google - - oauth_github - put: + $ref: '#/components/schemas/Error' + /projects/{id}/auth/users/{userId}/unban: + post: tags: - - Auth Configuration - summary: Configure authentication methods (unified) + - Auth Admin + summary: Unban a user description: | - Configure all authentication methods in a single request. - At least one method must remain enabled. - operationId: configureAuthMethods + Removes a ban from a user, restoring their ability to sign in. + The user's status is set back to 'active'. + operationId: unbanAuthUser security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - requestBody: - content: - application/json: - schema: - type: object - properties: - enable_email_password: - type: boolean - enable_anonymous: - type: boolean - oauth_providers: - type: array - items: - type: object - properties: - provider: - type: string - enabled: - type: boolean + - name: userId + in: path + required: true + schema: + type: string + format: uuid responses: '200': - description: Methods configured - '400': - description: At least one method must be enabled - /projects/{id}/oauth/configs: + description: User unbanned successfully + content: + application/json: + schema: + $ref: '#/components/schemas/UnbanUserResponse' + '404': + description: User not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/email-templates: get: tags: - - OAuth Configuration - summary: List OAuth configurations - description: List all OAuth provider configurations for this project - operationId: listOAuthConfigs + - Auth Configuration + summary: List email templates + description: Returns all custom email templates for this project. + operationId: listEmailTemplates security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' responses: '200': - description: List of OAuth configurations + description: Email templates list content: application/json: schema: type: object properties: - configs: + data: type: array items: - $ref: '#/components/schemas/OAuthConfig' + $ref: '#/components/schemas/EmailTemplate' post: tags: - - OAuth Configuration - summary: Create OAuth configuration - description: Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device) - operationId: createOAuthConfig + - Auth Configuration + summary: Create email template + description: | + Creates a custom email template for the project. Custom email templates + are a SUPERAGENT feature: requests from a HOBBY project owner are + rejected with 403, and HOBBY projects always send the built-in default + templates regardless of any previously saved custom rows. + Every project is created with one template per type, so customizing one + is usually a PUT; creating a type the project already has returns 409. + Valid template types: welcome, confirmation, password_reset, password_changed + operationId: createEmailTemplate security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' requestBody: @@ -9662,1185 +9964,990 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/CreateOAuthConfigRequest' + $ref: '#/components/schemas/CreateEmailTemplateRequest' responses: '201': - description: OAuth config created + description: Template created content: application/json: schema: - $ref: '#/components/schemas/OAuthConfig' - '409': - description: Provider already configured - /projects/{id}/oauth/configs/{provider}: - get: - tags: - - OAuth Configuration - summary: Get OAuth configuration - operationId: getOAuthConfig + $ref: '#/components/schemas/EmailTemplate' + '400': + description: Invalid template type + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Custom email templates require the SUPERAGENT plan + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: The project already has a template of this type + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/email-templates/{type}: + get: + tags: + - Auth Configuration + summary: Get email template + operationId: getEmailTemplate security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: provider + - name: type in: path required: true schema: type: string enum: - - google - - github - - microsoft - - apple - - device - - name: client_id - in: query - required: false - schema: - type: string - description: Required when `provider=device` to select a specific device client. + - welcome + - confirmation + - password_reset + - password_changed responses: '200': - description: OAuth configuration + description: Email template content: application/json: schema: - $ref: '#/components/schemas/OAuthConfig' + $ref: '#/components/schemas/EmailTemplate' + '404': + description: Template not found put: tags: - - OAuth Configuration - summary: Update OAuth configuration - operationId: updateOAuthConfig + - Auth Configuration + summary: Update email template + description: | + Updates a custom email template. Custom email templates are a SUPERAGENT + feature: requests from a HOBBY project owner are rejected with 403 + (including after a downgrade), so a HOBBY project cannot modify + templates and always sends the built-in defaults. + operationId: updateEmailTemplate security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: provider + - name: type in: path required: true schema: type: string enum: - - google - - github - - microsoft - - apple - - device - - name: client_id - in: query - required: false - schema: - type: string - description: Required when `provider=device` to select a specific device client. + - welcome + - confirmation + - password_reset + - password_changed requestBody: + required: true content: application/json: schema: - $ref: '#/components/schemas/UpdateOAuthConfigRequest' + $ref: '#/components/schemas/UpdateEmailTemplateRequest' responses: '200': - description: OAuth config updated + description: Template updated content: application/json: schema: - $ref: '#/components/schemas/OAuthConfig' + $ref: '#/components/schemas/EmailTemplate' + '403': + description: Custom email templates require the SUPERAGENT plan + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Template not found delete: tags: - - OAuth Configuration - summary: Delete OAuth configuration - operationId: deleteOAuthConfig + - Auth Configuration + summary: Delete email template + description: | + Deletes a custom template, reverting to the default. Custom email + templates are a SUPERAGENT feature: requests from a HOBBY project owner + are rejected with 403. + operationId: deleteEmailTemplate security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: provider + - name: type in: path required: true schema: type: string enum: - - google - - github - - microsoft - - apple - - device - - name: client_id - in: query - required: false - schema: - type: string - description: Required when `provider=device` to select a specific device client. + - welcome + - confirmation + - password_reset + - password_changed responses: '204': - description: OAuth config deleted - /projects/{id}/oauth/providers: + description: Template deleted + '403': + description: Custom email templates require the SUPERAGENT plan + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Template not found + /email-templates/defaults: get: tags: - - OAuth Configuration - summary: List available OAuth providers - description: Get list of supported OAuth providers and their default scopes - operationId: listAvailableOAuthProviders - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - Auth Configuration + summary: Get default email templates + description: Returns the default email templates used when no custom template is configured. + operationId: getDefaultEmailTemplates responses: '200': - description: Available providers + description: Default templates content: application/json: schema: type: object properties: - providers: + data: type: array items: - type: object - properties: - id: - type: string - name: - type: string - default_scopes: - type: array - items: - type: string - /auth/oauth/{provider}/authorize: + $ref: '#/components/schemas/EmailTemplate' + /email-templates/defaults/{type}: get: tags: - - OAuth Authentication - summary: Start OAuth authorization - description: | - Redirects user to OAuth provider for authorization. - Handles CSRF protection with state parameter. - Project is identified via the anon_key query parameter. - operationId: authOAuthAuthorize + - Auth Configuration + summary: Get default email template by type + operationId: getDefaultEmailTemplate parameters: - - name: provider + - name: type in: path required: true schema: type: string enum: - - google - - github - - microsoft - - apple - - name: anon_key - in: query - required: true - schema: - type: string - description: Project anon key (required - identifies the project) - - name: redirect_url - in: query - schema: - type: string - description: | - URL to redirect to after the OAuth flow (optional). Must exactly - match an entry in the project's `allowed_redirect_urls`, including - its query string, or be the project's own managed hosted-auth page - URL. - - name: client_state - in: query - schema: - type: string - maxLength: 255 - description: | - Optional application nonce. It is stored with the server-generated - provider state and echoed to redirect_url as `state`. - - name: response_mode - in: query - schema: - type: string - enum: - - code - description: | - Set to `code` to receive a short-lived authorization code at - redirect_url, then use POST /auth/oauth/exchange to obtain the - session. `redirect_url` is required in this mode. When omitted, the - established session-fragment response is retained for compatibility - with existing clients. + - welcome + - confirmation + - password_reset + - password_changed responses: - '307': - description: Redirect to OAuth provider - '400': - description: | - OAuth provider is disabled for this project, or `redirect_url` is - not registered in `allowed_redirect_urls` + '200': + description: Default template + content: + application/json: + schema: + $ref: '#/components/schemas/EmailTemplate' '404': - description: OAuth provider not configured - /auth/oauth/{provider}/callback: + description: Template type not found + /projects/{id}/auth/config: get: tags: - - OAuth Authentication - summary: OAuth callback handler - description: | - Handles OAuth provider callback with authorization code. - Exchanges code for tokens and creates/signs in user. - operationId: authOAuthCallback + - Auth Configuration + summary: Get auth configuration + operationId: getAuthConfig + security: + - UserToken: [] + - ProjectAccessToken: [] parameters: - - name: provider - in: path - required: true - schema: - type: string - enum: - - google - - github - - microsoft - - apple - - name: code - in: query - required: true - schema: - type: string - - name: state - in: query - required: true - schema: - type: string - - name: error - in: query - schema: - type: string + - $ref: '#/components/parameters/ProjectId' responses: '200': - description: Existing user signed in (when redirect_url was omitted) - content: - application/json: - schema: - $ref: '#/components/schemas/AuthTokenResponse' - '201': - description: New user created and signed in (when redirect_url was omitted) + description: Auth configuration content: application/json: schema: - $ref: '#/components/schemas/AuthTokenResponse' - '303': - description: | - Redirect to the exact registered redirect_url. Flows that requested - response_mode=code receive a short-lived, single-use `code` and - optional application `state`; compatibility flows receive the - established session fragment. - '400': - description: | - Missing/invalid code or state, the state parameter expired, or the - flow's stored redirect_url is no longer registered in - allowed_redirect_urls (re-checked at callback time) - '403': - description: | - The provider's email domain is not in `allowed_email_domains`. Creating - an account is refused under `signup` and `signup_and_signin`; signing in - an already-linked account is refused under `signup_and_signin`. - '409': - description: Email already exists (requires linking) - /auth/oauth/exchange: - post: + $ref: '#/components/schemas/AuthConfig' + put: tags: - - OAuth Authentication - summary: Exchange OAuth authorization code + - Auth Configuration + summary: Update auth configuration description: | - Atomically consumes a short-lived callback code and returns the user's - session. The request must use the same project anon key and exact - redirect_url that initiated the flow. - operationId: authOAuthExchange + Updates the project's auth configuration. Only the fields present in + the body are changed. + operationId: updateAuthConfig security: - - AnonKey: [] + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' requestBody: - required: true content: application/json: schema: - type: object - required: - - code - - redirect_url - properties: - code: - type: string - redirect_url: - type: string - format: uri + $ref: '#/components/schemas/UpdateAuthConfigRequest' responses: '200': - description: Authorization code consumed and session created + description: Configuration updated content: application/json: schema: - $ref: '#/components/schemas/AuthTokenResponse' - '400': - description: Invalid, expired, consumed, or redirect-mismatched code - '401': - description: Missing or invalid project anon key + $ref: '#/components/schemas/AuthConfig' '403': description: | - Email confirmation is now required, or the account's email domain is not - in `allowed_email_domains` while `allowed_email_domains_mode` is - `signup_and_signin`. Both are re-checked here because the code outlives - the callback that issued it. - '429': - description: Too many exchange attempts from this client - /auth/device/authorize: + The update would turn on, widen, or otherwise edit the email domain + allowlist (`allowed_email_domains`, `allowed_email_domains_mode`) + for a project that is not on the SUPERAGENT plan. A HOBBY project keeps + whatever allowlist it already has — parked, enforcing nothing until + it upgrades — and may still remove it, so a downgrade never leaves a + project locked out of its own signups. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/auth/config/test-email: post: tags: - - OAuth Authentication - summary: Start RFC8628 device authorization + - Auth Configuration + summary: Send a test email using the project's saved SMTP config description: | - Starts OAuth 2.0 Device Authorization Grant (RFC 8628). - Returns `device_code` for the CLI and `user_code` for browser verification. - - By default the returned `verification_uri` / `verification_uri_complete` - point at the project's managed device-approval page served by this API - (`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`), - which requires managed auth enabled and a default anon key for the - project. - - Projects can override this by setting `device_verification_url` on the - auth config (`PATCH /auth/config`). When set, that URL is returned as-is - with the `user_code` appended (no `action=device` hint and no embedded - anon key — the page brings its own), so a CLI's `login` command surfaces - the project's own RFC 8628 approval page. With a custom URL, device login - does **not** require managed auth to be enabled; the custom page's origin - must be in the project's auth CORS allowlist to call - `POST /auth/device/verify`. Either way the verification page must - authenticate the end user and call `POST /auth/device/verify` with the - `user_code`. See the device-auth guide for both approaches. - operationId: authDeviceAuthorize + Sends a diagnostic email to `to_email` using the project's + persisted `auth_config` SMTP credentials. If `html_body` or + `text_body` is supplied, the override path is taken: those + values (plus optional `subject`) are rendered through + html/text templates against the project's `Data` and + used as the body — used by the template editor's "Send Test" + affordance to preview an unsaved template. With both bodies + omitted, a hardcoded diagnostic message is sent and any + `subject` field is ignored. Sending `subject` alone (no + bodies) is rejected with 400 to avoid a silently-dropped + subject or a blank message. Also rejects with 400 if + `email_enabled=false` or `smtp_host` is empty. + operationId: testEmailConfig + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: application/json: schema: - type: object - required: - - client_id - properties: - client_id: - type: string - description: Enabled `device` OAuth client ID for the target project + $ref: '#/components/schemas/TestEmailRequest' responses: '200': - description: Device authorization started + description: Test email sent content: application/json: schema: - $ref: '#/components/schemas/DeviceAuthorizationResponse' + $ref: '#/components/schemas/TestEmailResponse' '400': - description: Invalid request or unauthorized client + description: Invalid request or email delivery not configured + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Project not found + '502': + description: Template render failure or SMTP delivery failed + /projects/{id}/auth/hosted-pages/{pageType}: + get: + tags: + - Auth Configuration + summary: Get hosted auth page + description: | + Returns the saved HTML/CSS for the page type, or `page: null` when the + project has not customized it yet. Always returns `defaults` (the theme + shell to seed an editor with, which is valid input to the update endpoint) + and `runtime` (the script the rendered page runs, plus a preview harness). + operationId: getAuthHostedPage + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: pageType + in: path + required: true + schema: + $ref: '#/components/schemas/HostedAuthPageType' + responses: + '200': + description: Hosted page loaded content: application/json: schema: - $ref: '#/components/schemas/OAuthErrorResponse' - /auth/device/token: - post: + $ref: '#/components/schemas/AuthHostedPageResponse' + put: tags: - - OAuth Authentication - summary: Poll device token endpoint + - Auth Configuration + summary: Update hosted auth page description: | - RFC8628 token polling endpoint. - Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and `expired_token`. - operationId: authDeviceToken + Saves the current HTML/CSS for this page type. + Security validation rejects script tags, javascript: URLs, inline event handlers, iframe/object/embed/meta/link tags in HTML, + and closing style/head tags in CSS. + operationId: updateAuthHostedPage + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: pageType + in: path + required: true + schema: + $ref: '#/components/schemas/HostedAuthPageType' requestBody: required: true content: application/json: schema: - type: object - required: - - grant_type - - device_code - - client_id - properties: - grant_type: - type: string - enum: - - urn:ietf:params:oauth:grant-type:device_code - device_code: - type: string - client_id: - type: string + $ref: '#/components/schemas/UpdateAuthHostedPageRequest' responses: '200': - description: Device flow completed, auth-user session minted + description: Hosted page updated content: application/json: schema: - $ref: '#/components/schemas/AuthTokenResponse' + $ref: '#/components/schemas/AuthHostedPageResponse' '400': - description: Polling state/error response + description: Invalid input or unsafe markup + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Project not found + /projects/{id}/auth/pages/appearance: + get: + tags: + - Auth Configuration + summary: Get managed auth page appearance + operationId: getAuthPageAppearance + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + responses: + '200': + description: Saved appearance and effective plan state content: application/json: schema: - $ref: '#/components/schemas/OAuthErrorResponse' - '403': - description: | - `access_denied` - the approving account's email domain is not in - `allowed_email_domains` while `allowed_email_domains_mode` is - `signup_and_signin`. Re-checked here because approval and redemption - are separate requests. + $ref: '#/components/schemas/AuthPageAppearanceResponse' + '401': + description: Unauthorized content: application/json: schema: - $ref: '#/components/schemas/OAuthErrorResponse' - /auth/device/verify: - post: + $ref: '#/components/schemas/Error' + '403': + description: Access denied + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Project not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Appearance could not be read + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/auth/pages/theme: + put: tags: - - OAuth Authentication - summary: Approve or deny a device code - description: | - Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a `user_code`. - - Called by the verification page after the end user signs in. The grant is - scoped to the project the auth-user token belongs to: approving a - `user_code` issued for a different project returns `403`. This endpoint - does not require managed auth to be enabled, so a custom verification page - (hosted anywhere) can drive approval — it just needs an authenticated - project auth-user access token and, for cross-origin browser calls, the - page origin allowed in the project's auth CORS settings. - operationId: authDeviceVerify + - Auth Configuration + summary: Save the managed auth page theme + operationId: updateAuthPageTheme security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: application/json: schema: - type: object - required: - - user_code - properties: - user_code: - type: string - action: - type: string - enum: - - approve - - deny - default: approve + $ref: '#/components/schemas/UpdateAuthPageThemeRequest' responses: '200': - description: Verification action accepted + description: Theme saved content: application/json: schema: - type: object - properties: - success: - type: boolean - status: - type: string + $ref: '#/components/schemas/UpdateAuthPageThemeRequest' + '400': + description: Invalid or unreadable theme + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '401': - description: Not authenticated + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/platform/exchange: - post: + '403': + description: Plan does not permit customisation + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Project not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Theme could not be saved + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: tags: - - OAuth Authentication - summary: Exchange auth-user device session for platform token - description: | - Exchanges a verified auth-user device-flow session into a platform token for CLI usage. - The target platform user is derived from authenticated auth-user mapping; client cannot select another user. - operationId: authPlatformExchange + - Auth Configuration + summary: Clear the managed auth page theme + operationId: deleteAuthPageTheme security: - - AuthUserAccessToken: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - client_id - properties: - client_id: - type: string + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' responses: - '200': - description: Platform token minted + '204': + description: Theme cleared + '401': + description: Unauthorized content: application/json: schema: - $ref: '#/components/schemas/PlatformExchangeResponse' + $ref: '#/components/schemas/Error' '403': - description: | - Exchange not allowed for this session/client/project, or the - account's email domain is not in `allowed_email_domains` while - `allowed_email_domains_mode` is `signup_and_signin`. The domain is - re-checked here because the minted platform token outlives the - session it is exchanged from. + description: Plan does not permit customisation content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/oauth/providers: - get: - tags: - - OAuth Authentication - summary: List user's linked providers - description: Get list of OAuth providers linked to current user - operationId: authListOAuthProviders - security: - - AuthUserAccessToken: [] - responses: - '200': - description: Linked providers + '404': + description: Project not found content: application/json: schema: - type: object - properties: - providers: - type: array - items: - type: object - properties: - provider: - type: string - linked_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - '401': - description: Not authenticated + $ref: '#/components/schemas/Error' + '500': + description: Theme could not be cleared content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/oauth/{provider}/link: - post: + /projects/{id}/auth/pages/{pageType}/layout: + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: pageType + in: path + required: true + schema: + $ref: '#/components/schemas/HostedAuthPageType' + put: tags: - - OAuth Authentication - summary: Link OAuth provider to current user - description: | - Generates authorization URL to link OAuth provider to existing account. - User must be authenticated. - operationId: authLinkOAuthProvider + - Auth Configuration + summary: Save one managed auth page layout + operationId: updateAuthPageLayout security: - - AuthUserAccessToken: [] - parameters: - - name: provider - in: path - required: true - schema: - type: string - enum: - - google - - github - - microsoft - - apple - - name: redirect_url - in: query - schema: - type: string - description: | - URL to redirect to after linking completes (optional). Same - allowed_redirect_urls requirement as GET /auth/oauth/{provider}/authorize. - - name: client_state - in: query - schema: - type: string - maxLength: 255 - description: | - Optional application nonce echoed to redirect_url as `state`. - - name: response_mode - in: query - schema: - type: string - enum: - - code - description: | - Set to `code` to receive a short-lived authorization code at - redirect_url. `redirect_url` is required in this mode. When - omitted, the established session-fragment response is retained for - compatibility with existing clients. + - UserToken: [] + - ProjectAccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateAuthPageLayoutRequest' responses: '200': - description: Authorization URL generated + description: Layout saved content: application/json: schema: - type: object - properties: - authorization_url: - type: string + $ref: '#/components/schemas/UpdateAuthPageLayoutRequest' '400': - description: redirect_url is not registered in allowed_redirect_urls + description: Invalid page type or layout content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Not authenticated + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Plan does not permit customisation content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: OAuth provider not configured + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: Provider already linked + '500': + description: Layout could not be saved content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/oauth/{provider}/unlink: delete: tags: - - OAuth Authentication - summary: Unlink OAuth provider - description: | - Remove OAuth provider from user's account. - Cannot unlink if it's the only authentication method. - operationId: authUnlinkOAuthProvider + - Auth Configuration + summary: Clear one managed auth page layout + operationId: deleteAuthPageLayout security: - - AuthUserAccessToken: [] - parameters: - - name: provider - in: path - required: true - schema: - type: string - enum: - - google - - github - - microsoft - - apple + - UserToken: [] + - ProjectAccessToken: [] responses: '204': - description: Provider unlinked + description: Layout cleared '400': - description: Cannot unlink last authentication method + description: Invalid page type content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Not authenticated - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Provider not linked + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/oauth/{provider}/refresh-token: - post: - tags: - - OAuth Authentication - summary: Refresh OAuth provider token - description: | - Refresh the access token for an OAuth provider using its refresh token. - Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos). - operationId: refreshOAuthProviderToken - security: - - AuthUserAccessToken: [] - parameters: - - name: provider - in: path - required: true - schema: - type: string - enum: - - google - - github - - microsoft - - apple - responses: - '200': - description: Token refreshed successfully - content: - application/json: - schema: - type: object - properties: - message: - type: string - provider: - type: string - expires_in: - type: integer - '400': - description: No refresh token available or refresh failed + '403': + description: Plan does not permit customisation content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Not authenticated + '404': + description: Project not found content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: Provider not linked + '500': + description: Layout could not be cleared content: application/json: schema: $ref: '#/components/schemas/Error' - /auth/oauth/{provider}/token: + /projects/{id}/auth/pages/{pageType}/preview: get: tags: - - OAuth Authentication - summary: Get current provider access token + - Auth Configuration + summary: Render a short-lived managed auth page preview description: | - Get valid access token for OAuth provider. - Automatically refreshes if expired. - operationId: getOAuthProviderToken - security: - - AuthUserAccessToken: [] + Public HTML endpoint for a preview URL returned by the POST operation. + The signed ticket contains the unsaved appearance, expires shortly, and + runs the production page runtime against mocked authentication responses. + operationId: renderAuthPagePreview + security: [] parameters: - - name: provider + - $ref: '#/components/parameters/ProjectId' + - name: pageType in: path required: true + schema: + $ref: '#/components/schemas/HostedAuthPageType' + - name: ticket + in: query + required: true schema: type: string - enum: - - google - - github - - microsoft - - apple + minLength: 1 + maxLength: 4096 + description: Short-lived signed preview ticket returned by the POST operation. responses: '200': - description: Current access token + description: Rendered preview document content: - application/json: + text/html: schema: - type: object - properties: - message: - type: string - provider: - type: string - expires_in: - type: integer - '401': - description: Not authenticated + type: string + '404': + description: Ticket is invalid or expired, its path does not match, or managed authentication is disabled content: - application/json: + text/plain: schema: - $ref: '#/components/schemas/Error' - '404': - description: Provider not linked + type: string + '500': + description: Preview could not be rendered content: - application/json: + text/plain: schema: - $ref: '#/components/schemas/Error' - /auth/oauth/{provider}/call-api: + type: string post: tags: - - OAuth Authentication - summary: Call OAuth provider API - description: | - Make an authenticated request to an OAuth provider's API on behalf of the user. - The user's stored access token is automatically used and refreshed if needed. - - The request is always sent to the provider's fixed API base URL joined with - the caller-supplied `endpoint`. `endpoint` must be a relative path beginning - with `/` (optionally with a query string); it cannot change the target host. - Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are - rejected with `400` so the request can never be redirected to another host. - - Examples of `endpoint`: - - Google userinfo: `/oauth2/v1/userinfo` - - GitHub repositories: `/user/repos` - - Microsoft Graph profile: `/me` - - The response wraps the provider's raw JSON value with request metadata. - An empty provider body is represented as `data: null`; the envelope - preserves the provider's HTTP status in `status_code`, including errors. - Provider response bodies are limited to 8 MiB after decompression. - Transport failures, invalid JSON (including invalid UTF-8), and oversized - bodies return `502`. Provider redirects to another origin are blocked and - return `400`. - operationId: callOAuthProviderAPI + - Auth Configuration + summary: Preview an unsaved managed auth page appearance + operationId: previewAuthPage security: - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - name: provider + - $ref: '#/components/parameters/ProjectId' + - name: pageType in: path required: true schema: - type: string - enum: - - google - - github - - microsoft - - apple + $ref: '#/components/schemas/HostedAuthPageType' requestBody: required: true content: application/json: schema: - type: object - required: - - endpoint - properties: - endpoint: - type: string - description: | - Relative path on the provider's API, beginning with `/`. It is - joined with the provider's fixed base URL; it must not contain a - scheme, host, userinfo, or a leading `//`. - example: /user/repos - method: - type: string - enum: - - GET - - POST - default: GET - description: HTTP method to use - body: - type: object - additionalProperties: true - description: Request body for POST requests + $ref: '#/components/schemas/PreviewAuthPageRequest' responses: '200': - description: Provider API response + description: Short-lived URL for the rendered preview document content: application/json: schema: - type: object - description: OAuth provider API response envelope - required: - - provider - - endpoint - - status_code - - data - properties: - provider: - type: string - enum: - - google - - github - - microsoft - - apple - endpoint: - type: string - status_code: - type: integer - minimum: 100 - maximum: 599 - data: - description: Raw provider JSON value, or null when the provider returns no body - nullable: true + $ref: '#/components/schemas/PreviewAuthPageResponse' '400': - description: | - Invalid request (for example: missing `endpoint`, an `endpoint` that is - not a relative path, or an unsupported HTTP method), or a provider - redirect to another origin. + description: Invalid page type or draft content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Not authenticated + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' - '404': - description: OAuth provider configuration not found + '403': + description: Access denied content: application/json: schema: $ref: '#/components/schemas/Error' - '500': - description: Failed to create the provider API request + '404': + description: Project not found or managed authentication is disabled content: application/json: schema: $ref: '#/components/schemas/Error' - '502': - description: Provider transport failure, invalid JSON, or response body larger than 8 MiB + '500': + description: Preview could not be rendered content: application/json: schema: $ref: '#/components/schemas/Error' - /projects/{id}/anon-keys: + /projects/{id}/auth/hosted/{pageType}: get: tags: - - Anon Keys - summary: List anon keys - description: | - Supports two mutually exclusive pagination modes. Offset mode uses `page` - and `limit` and is the default when neither `cursor` nor `search` is - supplied (first page, default `limit`). Cursor mode uses `cursor` and - `limit`, supports `search` (case-insensitive name match), and returns - `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`) - returns 400. - operationId: listAnonKeys - security: - - UserToken: [] + - Auth Configuration + summary: Render a managed auth page + description: | + Public HTML endpoint for signup, forgot-password, device approval, + verify-email, and reset-password pages. Login uses the path without a + page type. + Requires `Accept: text/html`. + Returns 404 when managed hosted pages are disabled for the project. + security: [] + operationId: renderManagedAuthPage parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' + - name: pageType + in: path + required: true + schema: + $ref: '#/components/schemas/HostedRenderablePageType' responses: '200': - description: List of anon keys + description: Hosted auth page HTML content: - application/json: + text/html: schema: - type: object - properties: - data: - type: array - items: - $ref: '#/components/schemas/AnonKey' - total: - type: integer - description: Total number of items matching the query (so the UI can render numbered pages). - has_more: - type: boolean - description: Whether a next page exists. - next_cursor: - type: string - description: Opaque cursor for the next page (cursor pagination only) - prev_cursor: - type: string - description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. - post: + type: string + '400': + description: Invalid project id or unsupported Accept header + '404': + description: Managed pages disabled or page type not found + /projects/{id}/auth/hosted: + get: tags: - - Anon Keys - summary: Create anon key - operationId: createAnonKey - security: - - UserToken: [] + - Auth Configuration + summary: Render default managed auth page + description: | + Public HTML endpoint for the managed login page. + Requires `Accept: text/html`. + security: [] + operationId: renderDefaultManagedAuthPage parameters: - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - name - properties: - name: - type: string - description: | - Key name for identification. - Can only contain letters, numbers, underscores, and hyphens. - pattern: ^[A-Za-z0-9_-]+$ - minLength: 1 - maxLength: 255 - example: frontend-app - permissions: - type: array - items: - type: string - enum: - - auth.signup - - auth.signin - - auth.refresh - - auth.logout - - auth.password_reset - - auth.confirm_email - - auth.resend_confirmation - - storage.upload - - storage.download - - storage.list - - storage.delete - - realtime.connect - - realtime.subscribe - - realtime.publish - - functions.invoke - description: | - Optional list of permissions for this key. - If not provided, defaults to auth-only permissions: auth.signup, auth.signin, auth.refresh, auth.logout, auth.password_reset, auth.confirm_email, auth.resend_confirmation. - Storage, realtime, and functions permissions must be explicitly added if needed. - example: - - auth.signup - - auth.signin - - auth.refresh - - auth.logout + - name: action + in: query + required: false + schema: + type: string + enum: + - login + - signup + - forgot-password + - device + description: | + Optional deep-link action for the unified hosted page. Ignored when a + custom login page is configured. `action=device` renders the device + authorization approval UI inline (no redirect to any external app); + it signs the user in and calls `POST /auth/device/verify`. + - name: user_code + in: query + required: false + schema: + type: string + description: Device user code (from `POST /auth/device/authorize`) used with `action=device`. + - name: anon_key + in: query + required: false + schema: + type: string + description: Project anon key used by built-in managed auth flows (required for login/signup/device actions). + - name: state + in: query + required: false + schema: + type: string + description: | + Opaque one-time nonce generated by the client SDK before redirecting + here. On successful login/signup it is echoed back in the post-auth + redirect fragment as `state`, so the SDK can bind the returned session + to the flow it initiated (login-CSRF / session-fixation defense). The + SDK rejects a returned session whose `state` does not match. responses: - '201': - description: Anon key created + '200': + description: Hosted auth page HTML content: - application/json: + text/html: schema: - $ref: '#/components/schemas/AnonKey' - /projects/{id}/anon-keys/{keyId}: + type: string + '400': + description: Invalid project id or unsupported Accept header + '404': + description: Managed pages disabled + /projects/{id}/auth/hosted/login/options: get: tags: - - Anon Keys - summary: Get anon key - description: Get details of a specific anon key - operationId: getAnonKey - security: - - UserToken: [] + - Auth Configuration + summary: Get hosted login runtime options + description: | + Returns runtime options for the built-in managed login flow. + Requires `anon_key` query parameter. + Rate limited per project and client IP. Excess requests return `429` and `Retry-After`. + security: [] + operationId: getHostedLoginOptions parameters: - $ref: '#/components/parameters/ProjectId' - - name: keyId - in: path + - name: anon_key + in: query required: true schema: type: string - format: uuid responses: '200': - description: Anon key details + description: Hosted login options returned content: application/json: schema: - $ref: '#/components/schemas/AnonKey' + $ref: '#/components/schemas/HostedLoginOptionsResponse' + '401': + description: Invalid or missing anon key '404': - description: Key not found - delete: + description: Managed pages disabled + '429': + description: Rate limit exceeded + /projects/{id}/auth/hosted/login/check-email: + post: tags: - - Anon Keys - summary: Revoke anon key - description: Revokes key - it will immediately stop working - operationId: revokeAnonKey - security: - - UserToken: [] + - Auth Configuration + summary: Check whether email exists for hosted login flow + description: | + Used by the built-in managed login page to branch UI between signin and signup. + Requires anon key in Authorization header. + Rate limited per project and client IP. Excess requests return `429` and `Retry-After`. + security: [] + operationId: hostedLoginCheckEmail parameters: - $ref: '#/components/parameters/ProjectId' - - name: keyId - in: path + - name: Authorization + in: header required: true schema: type: string - format: uuid + description: Bearer anon key (`Bearer `) + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/HostedLoginEmailCheckRequest' responses: - '204': - description: Key revoked - '401': - description: Unauthorized - '403': - description: Forbidden - '404': - description: Key not found - '409': - description: Cannot delete the project's default anon key - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error + '200': + description: Email existence evaluated content: application/json: schema: - $ref: '#/components/schemas/Error' - /projects/{id}/anon-keys/{keyId}/regenerate: - post: - tags: - - Anon Keys - summary: Regenerate anon key - description: Generate new JWT value for existing key - operationId: regenerateAnonKey - security: + $ref: '#/components/schemas/HostedLoginEmailCheckResponse' + '401': + description: Invalid or missing anon key + '429': + description: Rate limit exceeded + /projects/{id}/auth/methods: + get: + tags: + - Auth Configuration + summary: Get all authentication methods + description: | + Returns all configured authentication methods for this project, + including email/password, anonymous, device authorization, and OAuth providers. + operationId: getAuthMethods + security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: keyId - in: path - required: true - schema: - type: string - format: uuid responses: '200': - description: Key regenerated + description: Authentication methods configuration content: application/json: schema: - $ref: '#/components/schemas/AnonKey' - /projects/{id}/anon-keys/{keyId}/set-default: - post: + type: object + properties: + email_password: + type: object + properties: + enabled: + type: boolean + method: + type: string + name: + type: string + anonymous: + type: object + properties: + enabled: + type: boolean + method: + type: string + name: + type: string + oauth_providers: + type: array + items: + type: object + properties: + enabled: + type: boolean + method: + type: string + provider: + type: string + name: + type: string + redirect_url: + type: string + scopes: + type: array + items: + type: string + available_methods: + type: array + items: + type: string + example: + - email_password + - oauth_google + - oauth_github + put: tags: - - Anon Keys - summary: Set default anon key - description: Promotes the given key to the project's configured default. At most one key per project can be default. - operationId: setDefaultAnonKey + - Auth Configuration + summary: Configure authentication methods (unified) + description: | + Configure all authentication methods in a single request. + At least one method must remain enabled. + operationId: configureAuthMethods security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: keyId - in: path - required: true - schema: - type: string - format: uuid + requestBody: + content: + application/json: + schema: + type: object + properties: + enable_email_password: + type: boolean + enable_anonymous: + type: boolean + oauth_providers: + type: array + items: + type: object + properties: + provider: + type: string + enabled: + type: boolean responses: '200': - description: Key set as default - content: - application/json: - schema: - $ref: '#/components/schemas/AnonKey' - '401': - description: Unauthorized - '403': - description: Forbidden - '404': - description: Anon key not found - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /projects/{id}/service-keys: + description: Methods configured + '400': + description: At least one method must be enabled + /projects/{id}/oauth/configs: get: tags: - - Service Keys - summary: List service keys (paginated) - description: | - List all service role keys for a project with pagination. - - **WARNING:** Service keys bypass RLS - for backend/admin use only! - operationId: listServiceKeys + - OAuth Configuration + summary: List OAuth configurations + description: List all OAuth provider configurations for this project + operationId: listOAuthConfigs security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' responses: '200': - description: Paginated list of service keys + description: List of OAuth configurations content: application/json: schema: - $ref: '#/components/schemas/PaginatedServiceKeys' + type: object + properties: + configs: + type: array + items: + $ref: '#/components/schemas/OAuthConfig' post: tags: - - Service Keys - summary: Create service key - description: | - Create a new service role key for admin operations. - - **WARNING:** Service keys bypass all RLS policies! - Store securely and NEVER expose in frontend code. - operationId: createServiceKey + - OAuth Configuration + summary: Create OAuth configuration + description: Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device) + operationId: createOAuthConfig security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' requestBody: @@ -10848,1613 +10955,4004 @@ paths: content: application/json: schema: - type: object - required: - - name - properties: - name: - type: string - description: | - Descriptive name for the key (e.g., "admin-dashboard", "background-jobs"). - Can only contain letters, numbers, underscores, and hyphens. - pattern: ^[A-Za-z0-9_-]+$ - minLength: 1 - maxLength: 255 - example: admin-dashboard - permissions: - type: array - items: - type: string - description: | - Optional least-privilege scope for the key. When omitted, empty, or - containing only blank strings, the key is granted full access (["*"]) - for backward compatibility. Provide an explicit list (e.g. - ["functions.invoke", "locks.manage"]) to restrict the key; "*" - grants everything. Scope enforcement applies to function invocation, - storage object operations, and project locks. - example: - - functions.invoke - - locks.manage + $ref: '#/components/schemas/CreateOAuthConfigRequest' responses: '201': - description: Service key created - save the key_value immediately! + description: OAuth config created content: application/json: schema: - $ref: '#/components/schemas/ServiceKey' + $ref: '#/components/schemas/OAuthConfig' '409': - description: Key with this name already exists - /projects/{id}/service-keys/{keyId}: + description: Provider already configured + /projects/{id}/oauth/configs/{provider}: get: tags: - - Service Keys - summary: Get service key - description: Get details of a specific service key - operationId: getServiceKey + - OAuth Configuration + summary: Get OAuth configuration + operationId: getOAuthConfig security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: keyId + - name: provider in: path required: true schema: type: string - format: uuid + enum: + - google + - github + - microsoft + - apple + - device + - name: client_id + in: query + required: false + schema: + type: string + description: Required when `provider=device` to select a specific device client. responses: '200': - description: Service key details + description: OAuth configuration content: application/json: schema: - $ref: '#/components/schemas/ServiceKey' - '404': - description: Key not found - delete: + $ref: '#/components/schemas/OAuthConfig' + put: tags: - - Service Keys - summary: Delete service key - description: | - Permanently delete a service key. - Any services using this key will immediately lose access. - operationId: deleteServiceKey + - OAuth Configuration + summary: Update OAuth configuration + operationId: updateOAuthConfig security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - name: keyId + - name: provider in: path required: true schema: type: string - format: uuid - responses: - '204': - description: Key deleted - /projects/{id}/service-keys/{keyId}/regenerate: - post: - tags: - - Service Keys - summary: Regenerate service key - description: | - Generate new JWT value for existing key. - The old key is immediately invalidated. - Update your backend services with the new key before regenerating in production. - operationId: regenerateServiceKey - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: keyId - in: path - required: true + enum: + - google + - github + - microsoft + - apple + - device + - name: client_id + in: query + required: false schema: type: string - format: uuid - responses: - '200': - description: Key regenerated - save the new key_value immediately! - content: - application/json: - schema: - $ref: '#/components/schemas/ServiceKey' - /projects/{id}/storage/buckets: - get: - tags: - - Storage Buckets - summary: List all storage buckets in a project - description: | - With no pagination params, returns the full bucket list as a bare array - (legacy). Supplying `cursor`, `ending_before`, `search`, or `limit` - switches to keyset (cursor) pagination and returns a paginated envelope - with `next_cursor`/`prev_cursor` and a filtered `total`. - operationId: listStorageBuckets - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/Limit' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' - responses: - '200': - description: | - Either the full bucket list (bare array, legacy) or a paginated - envelope when cursor pagination is requested. - content: - application/json: - schema: - oneOf: - - type: array - items: - $ref: '#/components/schemas/StorageBucket' - - $ref: '#/components/schemas/PaginatedStorageBuckets' - post: - tags: - - Storage Buckets - summary: Create a new storage bucket - operationId: createStorageBucket - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateStorageBucketRequest' - responses: - '201': - description: Bucket created - content: - application/json: - schema: - $ref: '#/components/schemas/StorageBucket' - '409': - description: Bucket already exists - /projects/{id}/storage/buckets/{bucketName}: - get: - tags: - - Storage Buckets - summary: Get storage bucket by name - operationId: getStorageBucket - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/BucketName' - responses: - '200': - description: Bucket details - content: - application/json: - schema: - $ref: '#/components/schemas/StorageBucket' - '404': - description: Bucket not found - patch: - tags: - - Storage Buckets - summary: Update storage bucket settings - operationId: updateStorageBucket - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/BucketName' + description: Required when `provider=device` to select a specific device client. requestBody: - required: true content: application/json: schema: - $ref: '#/components/schemas/UpdateStorageBucketRequest' + $ref: '#/components/schemas/UpdateOAuthConfigRequest' responses: '200': - description: Bucket updated + description: OAuth config updated content: application/json: schema: - $ref: '#/components/schemas/StorageBucket' + $ref: '#/components/schemas/OAuthConfig' delete: tags: - - Storage Buckets - summary: Delete storage bucket and all objects - operationId: deleteStorageBucket + - OAuth Configuration + summary: Delete OAuth configuration + operationId: deleteOAuthConfig security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/BucketName' + - name: provider + in: path + required: true + schema: + type: string + enum: + - google + - github + - microsoft + - apple + - device + - name: client_id + in: query + required: false + schema: + type: string + description: Required when `provider=device` to select a specific device client. responses: - '200': - description: Bucket deleted - /projects/{id}/storage/buckets/{bucketName}/policies: + '204': + description: OAuth config deleted + /projects/{id}/oauth/providers: get: tags: - - Storage Policies - summary: List storage policies for a bucket - operationId: listStoragePolicies + - OAuth Configuration + summary: List available OAuth providers + description: Get list of supported OAuth providers and their default scopes + operationId: listAvailableOAuthProviders security: - UserToken: [] + - ProjectAccessToken: [] parameters: - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/BucketName' responses: '200': - description: List of policies - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/StoragePolicy' - post: - tags: - - Storage Policies - summary: Create a storage policy - operationId: createStoragePolicy - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/BucketName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateStoragePolicyRequest' - responses: - '201': - description: Policy created + description: Available providers content: application/json: schema: - $ref: '#/components/schemas/StoragePolicy' - /projects/{id}/storage/buckets/{bucketName}/policies/{policyId}: - delete: + type: object + properties: + providers: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + default_scopes: + type: array + items: + type: string + /auth/oauth/{provider}/authorize: + get: tags: - - Storage Policies - summary: Delete a storage policy - operationId: deleteStoragePolicy - security: - - UserToken: [] + - OAuth Authentication + summary: Start OAuth authorization + description: | + Redirects user to OAuth provider for authorization. + Handles CSRF protection with state parameter. + Project is identified via the anon_key query parameter. + operationId: authOAuthAuthorize parameters: - - $ref: '#/components/parameters/ProjectId' - - $ref: '#/components/parameters/BucketName' - - name: policyId + - name: provider in: path required: true schema: type: string - format: uuid - responses: - '200': - description: Policy deleted - /projects/{id}/storage/objects: - get: - tags: - - Storage Admin - summary: List all storage objects in a project - description: | - Returns a paginated list of all storage objects across all buckets in the project. - Supports filtering by owner and pagination. - operationId: listStorageObjectsAdmin - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' - - name: owner_id + enum: + - google + - github + - microsoft + - apple + - name: anon_key in: query - description: Filter by owner user ID + required: true schema: type: string - format: uuid - - name: page + description: Project anon key (required - identifies the project) + - name: redirect_url in: query - description: Page number (1-based) schema: - type: integer - default: 1 - minimum: 1 - - name: limit + type: string + description: | + URL to redirect to after the OAuth flow (optional). Must exactly + match an entry in the project's `allowed_redirect_urls`, including + its query string, or be the project's own managed hosted-auth page + URL. + - name: client_state in: query - description: Items per page schema: - type: integer - default: 50 - minimum: 1 - maximum: 100 - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/EndingBefore' - - $ref: '#/components/parameters/Offset' - - $ref: '#/components/parameters/Search' + type: string + maxLength: 255 + description: | + Optional application nonce. It is stored with the server-generated + provider state and echoed to redirect_url as `state`. + - name: response_mode + in: query + schema: + type: string + enum: + - code + description: | + Set to `code` to receive a short-lived authorization code at + redirect_url, then use POST /auth/oauth/exchange to obtain the + session. `redirect_url` is required in this mode. When omitted, the + established session-fragment response is retained for compatibility + with existing clients. responses: - '200': - description: Paginated list of storage objects - content: - application/json: - schema: - type: object - properties: - data: - type: array - items: - $ref: '#/components/schemas/StorageObjectWithBucket' - page: - type: integer - limit: - type: integer - total: - type: integer - has_more: - type: boolean - next_cursor: - type: string - description: Opaque cursor for the next page (cursor pagination only) - prev_cursor: - type: string - description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. - /projects/{id}/storage/stats: + '307': + description: Redirect to OAuth provider + '400': + description: | + OAuth provider is disabled for this project, or `redirect_url` is + not registered in `allowed_redirect_urls` + '404': + description: OAuth provider not configured + /auth/oauth/{provider}/callback: get: tags: - - Storage Admin - summary: Get storage statistics for a project - description: Returns aggregate storage statistics including bucket count, object count, and total size. - operationId: getStorageStats - security: - - UserToken: [] + - OAuth Authentication + summary: OAuth callback handler + description: | + Handles OAuth provider callback with authorization code. + Exchanges code for tokens and creates/signs in user. + operationId: authOAuthCallback parameters: - - $ref: '#/components/parameters/ProjectId' + - name: provider + in: path + required: true + schema: + type: string + enum: + - google + - github + - microsoft + - apple + - name: code + in: query + required: true + schema: + type: string + - name: state + in: query + required: true + schema: + type: string + - name: error + in: query + schema: + type: string responses: '200': - description: Storage statistics + description: Existing user signed in (when redirect_url was omitted) content: application/json: schema: - $ref: '#/components/schemas/StorageStats' - /projects/{id}/realtime/config: - get: + $ref: '#/components/schemas/AuthTokenResponse' + '201': + description: New user created and signed in (when redirect_url was omitted) + content: + application/json: + schema: + $ref: '#/components/schemas/AuthTokenResponse' + '303': + description: | + Redirect to the exact registered redirect_url. Flows that requested + response_mode=code receive a short-lived, single-use `code` and + optional application `state`; compatibility flows receive the + established session fragment. + '400': + description: | + Missing/invalid code or state, the state parameter expired, or the + flow's stored redirect_url is no longer registered in + allowed_redirect_urls (re-checked at callback time) + '403': + description: | + The provider's email domain is not in `allowed_email_domains`. Creating + an account is refused under `signup` and `signup_and_signin`; signing in + an already-linked account is refused under `signup_and_signin`. + '409': + description: Email already exists (requires linking) + /auth/oauth/exchange: + post: tags: - - Realtime - summary: Get realtime configuration for a project - description: Returns the realtime configuration including enabled features and limits. - operationId: getRealtimeConfig + - OAuth Authentication + summary: Exchange OAuth authorization code + description: | + Atomically consumes a short-lived callback code and returns the user's + session. The request must use the same project anon key and exact + redirect_url that initiated the flow. + operationId: authOAuthExchange security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - AnonKey: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - code + - redirect_url + properties: + code: + type: string + redirect_url: + type: string + format: uri responses: '200': - description: Realtime configuration + description: Authorization code consumed and session created content: application/json: schema: - $ref: '#/components/schemas/RealtimeConfig' + $ref: '#/components/schemas/AuthTokenResponse' + '400': + description: Invalid, expired, consumed, or redirect-mismatched code '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Project not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - put: + description: Missing or invalid project anon key + '403': + description: | + Email confirmation is now required, or the account's email domain is not + in `allowed_email_domains` while `allowed_email_domains_mode` is + `signup_and_signin`. Both are re-checked here because the code outlives + the callback that issued it. + '429': + description: Too many exchange attempts from this client + /auth/device/authorize: + post: tags: - - Realtime - summary: Update realtime configuration for a project - description: Updates realtime settings including feature toggles and limits. - operationId: updateRealtimeConfig - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - OAuth Authentication + summary: Start RFC8628 device authorization + description: | + Starts OAuth 2.0 Device Authorization Grant (RFC 8628). + Returns `device_code` for the CLI and `user_code` for browser verification. + + By default the returned `verification_uri` / `verification_uri_complete` + point at the project's managed device-approval page served by this API + (`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`), + which requires managed auth enabled and a default anon key for the + project. + + Projects can override this by setting `device_verification_url` on the + auth config (`PATCH /auth/config`). When set, that URL is returned as-is + with the `user_code` appended (no `action=device` hint and no embedded + anon key — the page brings its own), so a CLI's `login` command surfaces + the project's own RFC 8628 approval page. With a custom URL, device login + does **not** require managed auth to be enabled; the custom page's origin + must be in the project's auth CORS allowlist to call + `POST /auth/device/verify`. Either way the verification page must + authenticate the end user and call `POST /auth/device/verify` with the + `user_code`. See the device-auth guide for both approaches. + operationId: authDeviceAuthorize requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/UpdateRealtimeConfigRequest' + type: object + required: + - client_id + properties: + client_id: + type: string + description: Enabled `device` OAuth client ID for the target project responses: '200': - description: Updated realtime configuration + description: Device authorization started content: application/json: schema: - $ref: '#/components/schemas/RealtimeConfig' + $ref: '#/components/schemas/DeviceAuthorizationResponse' '400': - description: Invalid configuration values - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '401': - description: Unauthorized + description: Invalid request or unauthorized client content: application/json: schema: - $ref: '#/components/schemas/Error' - /projects/{id}/realtime/stats: - get: + $ref: '#/components/schemas/OAuthErrorResponse' + /auth/device/token: + post: tags: - - Realtime - summary: Get realtime statistics for a project - description: Returns realtime usage statistics including connection counts and subscribed tables. - operationId: getRealtimeStats - security: - - UserToken: [] - parameters: - - $ref: '#/components/parameters/ProjectId' + - OAuth Authentication + summary: Poll device token endpoint + description: | + RFC8628 token polling endpoint. + Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and `expired_token`. + operationId: authDeviceToken + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - grant_type + - device_code + - client_id + properties: + grant_type: + type: string + enum: + - urn:ietf:params:oauth:grant-type:device_code + device_code: + type: string + client_id: + type: string responses: '200': - description: Realtime statistics + description: Device flow completed, auth-user session minted content: application/json: schema: - $ref: '#/components/schemas/RealtimeStats' - '401': - description: Unauthorized + $ref: '#/components/schemas/AuthTokenResponse' + '400': + description: Polling state/error response content: application/json: schema: - $ref: '#/components/schemas/Error' - /storage/{bucketName}: - get: - tags: - - Storage Objects - summary: List objects in a bucket - operationId: listStorageObjects - security: - - AnonKey: [] - - ServiceRoleKey: [] - - AuthUserAccessToken: [] - parameters: - - $ref: '#/components/parameters/BucketName' - - name: prefix - in: query - description: Filter objects by path prefix - schema: - type: string - - name: limit - in: query - description: Maximum objects to return - schema: - type: integer - default: 50 - maximum: 1000 - - name: cursor - in: query - description: Pagination cursor - schema: - type: string - responses: - '200': - description: List of objects + $ref: '#/components/schemas/OAuthErrorResponse' + '403': + description: | + `access_denied` - the approving account's email domain is not in + `allowed_email_domains` while `allowed_email_domains_mode` is + `signup_and_signin`. Re-checked here because approval and redemption + are separate requests. content: application/json: schema: - $ref: '#/components/schemas/StorageListResponse' - '403': - description: Access denied by storage policy - '429': - $ref: '#/components/responses/BandwidthCapExceeded' - /locks/{key}/lease: + $ref: '#/components/schemas/OAuthErrorResponse' + /auth/device/verify: post: tags: - - Locks - summary: Acquire a project lock + - OAuth Authentication + summary: Approve or deny a device code description: | - Acquires a project-scoped lease using the project embedded in the service-role key. - The caller must hold the `locks.manage` permission. Repeating the request with the - same lock token is idempotent and resets that lease to the requested TTL. A different - live owner receives `409 lock_held`; a caller whose own lease already lapsed receives - `409 lock_ownership_lost`. - operationId: acquireProjectLock + Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a `user_code`. + + Called by the verification page after the end user signs in. The grant is + scoped to the project the auth-user token belongs to: approving a + `user_code` issued for a different project returns `403`. This endpoint + does not require managed auth to be enabled, so a custom verification page + (hosted anywhere) can drive approval — it just needs an authenticated + project auth-user access token and, for cross-origin browser calls, the + page origin allowed in the project's auth CORS settings. + operationId: authDeviceVerify security: - - ServiceRoleKey: [] - parameters: - - $ref: '#/components/parameters/LockKey' - - $ref: '#/components/parameters/LockToken' - - $ref: '#/components/parameters/LockRequestId' + - AuthUserAccessToken: [] requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/ProjectLockLeaseRequest' + type: object + required: + - user_code + properties: + user_code: + type: string + action: + type: string + enum: + - approve + - deny + default: approve responses: - '201': - description: Lease acquired - content: - application/json: - schema: - $ref: '#/components/schemas/ProjectLockLease' - '400': - description: Invalid lock key, token, or TTL + '200': + description: Verification action accepted content: application/json: schema: - $ref: '#/components/schemas/Error' + type: object + properties: + success: + type: boolean + status: + type: string '401': - description: Missing or invalid credentials - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: A non-service credential was supplied or the service key lacks `locks.manage` - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '409': - description: | - The lock is held by another live lease (`lock_held`), or the caller's own lease - lapsed and is not yet reclaimable (`lock_ownership_lost`). - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '429': - description: Project lock request limit exceeded - headers: - Retry-After: - description: Seconds until the current fixed-minute window ends. - schema: - type: integer - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '503': - description: Lock service unavailable + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - patch: + /auth/platform/exchange: + post: tags: - - Locks - summary: Renew a project lock + - OAuth Authentication + summary: Exchange auth-user device session for platform token description: | - Renews a lease owned by the supplied lock token. The request must arrive - more than one second before `expires_at`; this safety margin prevents - clock skew between regional API instances from resurrecting an expired - lease. - operationId: renewProjectLock + Exchanges a verified auth-user device-flow session into a platform token for CLI usage. + The target platform user is derived from authenticated auth-user mapping; client cannot select another user. + operationId: authPlatformExchange security: - - ServiceRoleKey: [] - parameters: - - $ref: '#/components/parameters/LockKey' - - $ref: '#/components/parameters/LockToken' - - $ref: '#/components/parameters/LockRequestId' + - AuthUserAccessToken: [] requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/ProjectLockLeaseRequest' + type: object + required: + - client_id + properties: + client_id: + type: string responses: '200': - description: Lease renewed + description: Platform token minted content: application/json: schema: - $ref: '#/components/schemas/ProjectLockLease' - '400': - description: Invalid lock key, token, or TTL + $ref: '#/components/schemas/PlatformExchangeResponse' + '403': + description: | + Exchange not allowed for this session/client/project, or the + account's email domain is not in `allowed_email_domains` while + `allowed_email_domains_mode` is `signup_and_signin`. The domain is + re-checked here because the minted platform token outlives the + session it is exchanged from. content: application/json: schema: $ref: '#/components/schemas/Error' - '401': - description: Missing or invalid credentials + /auth/oauth/providers: + get: + tags: + - OAuth Authentication + summary: List user's linked providers + description: Get list of OAuth providers linked to current user + operationId: authListOAuthProviders + security: + - AuthUserAccessToken: [] + responses: + '200': + description: Linked providers content: application/json: schema: - $ref: '#/components/schemas/Error' - '403': - description: A non-service credential was supplied or the service key lacks `locks.manage` + type: object + properties: + providers: + type: array + items: + type: object + properties: + provider: + type: string + linked_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '409': - description: The lease expired or is owned by another token - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '429': - description: Project lock request limit exceeded - headers: - Retry-After: - description: Seconds until the current fixed-minute window ends. - schema: - type: integer - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '503': - description: Lock service unavailable - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - delete: + /auth/oauth/{provider}/link: + post: tags: - - Locks - summary: Release a project lock - description: Releases a lease only when the supplied lock token still owns it. - operationId: releaseProjectLock + - OAuth Authentication + summary: Link OAuth provider to current user + description: | + Generates authorization URL to link OAuth provider to existing account. + User must be authenticated. + operationId: authLinkOAuthProvider security: - - ServiceRoleKey: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/LockKey' - - $ref: '#/components/parameters/LockToken' - - $ref: '#/components/parameters/LockRequestId' + - name: provider + in: path + required: true + schema: + type: string + enum: + - google + - github + - microsoft + - apple + - name: redirect_url + in: query + schema: + type: string + description: | + URL to redirect to after linking completes (optional). Same + allowed_redirect_urls requirement as GET /auth/oauth/{provider}/authorize. + - name: client_state + in: query + schema: + type: string + maxLength: 255 + description: | + Optional application nonce echoed to redirect_url as `state`. + - name: response_mode + in: query + schema: + type: string + enum: + - code + description: | + Set to `code` to receive a short-lived authorization code at + redirect_url. `redirect_url` is required in this mode. When + omitted, the established session-fragment response is retained for + compatibility with existing clients. responses: - '204': - description: Lease released + '200': + description: Authorization URL generated + content: + application/json: + schema: + type: object + properties: + authorization_url: + type: string '400': - description: Invalid lock key or token + description: redirect_url is not registered in allowed_redirect_urls content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Missing or invalid credentials + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: A non-service credential was supplied or the service key lacks `locks.manage` + '404': + description: OAuth provider not configured content: application/json: schema: $ref: '#/components/schemas/Error' '409': - description: The lease is owned by another token + description: Provider already linked content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - description: Project lock request limit exceeded - headers: - Retry-After: - description: Seconds until the current fixed-minute window ends. + /auth/oauth/{provider}/unlink: + delete: + tags: + - OAuth Authentication + summary: Unlink OAuth provider + description: | + Remove OAuth provider from user's account. + Cannot unlink if it's the only authentication method. + operationId: authUnlinkOAuthProvider + security: + - AuthUserAccessToken: [] + parameters: + - name: provider + in: path + required: true + schema: + type: string + enum: + - google + - github + - microsoft + - apple + responses: + '204': + description: Provider unlinked + '400': + description: Cannot unlink last authentication method + content: + application/json: schema: - type: integer + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Lock service unavailable + '404': + description: Provider not linked content: application/json: schema: $ref: '#/components/schemas/Error' - /locks/{key}: - get: + /auth/oauth/{provider}/refresh-token: + post: tags: - - Locks - summary: Read a project lock + - OAuth Authentication + summary: Refresh OAuth provider token description: | - Reports whether the lock is currently held, when its lease expires, and the - holder's fencing token. `held` follows takeover eligibility rather than raw - expiry, so `held: false` means an acquire would succeed now. No lock token is - required, making this usable for monitoring and recovery. - operationId: getProjectLock + Refresh the access token for an OAuth provider using its refresh token. + Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos). + operationId: refreshOAuthProviderToken security: - - ServiceRoleKey: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/LockKey' - - $ref: '#/components/parameters/LockRequestId' + - name: provider + in: path + required: true + schema: + type: string + enum: + - google + - github + - microsoft + - apple responses: '200': - description: Current lock state + description: Token refreshed successfully content: application/json: schema: - $ref: '#/components/schemas/ProjectLockState' + type: object + properties: + message: + type: string + provider: + type: string + expires_in: + type: integer '400': - description: Invalid lock key + description: No refresh token available or refresh failed content: application/json: schema: $ref: '#/components/schemas/Error' '401': - description: Missing or invalid credentials - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '403': - description: A non-service credential was supplied or the service key lacks `locks.manage` - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '429': - description: Project lock request limit exceeded - headers: - Retry-After: - description: Seconds until the current fixed-minute window ends. - schema: - type: integer + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '503': - description: Lock service unavailable + '404': + description: Provider not linked content: application/json: schema: $ref: '#/components/schemas/Error' - delete: + /auth/oauth/{provider}/token: + get: tags: - - Locks - summary: Force release a project lock + - OAuth Authentication + summary: Get current provider access token description: | - Drops the lease whatever token holds it, for recovering a lock whose holder - died without releasing. Use `DELETE /locks/{key}/lease` for normal release. - - This breaks mutual exclusion by itself: the previous holder keeps working - until its own renewal fails. Guard the protected resource with the lease's - `fencing_token`, which the next acquisition raises, so a write from the - displaced holder can be rejected. Succeeds when the lock is already absent. - operationId: forceReleaseProjectLock + Get valid access token for OAuth provider. + Automatically refreshes if expired. + operationId: getOAuthProviderToken security: - - ServiceRoleKey: [] + - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/LockKey' - - $ref: '#/components/parameters/LockRequestId' + - name: provider + in: path + required: true + schema: + type: string + enum: + - google + - github + - microsoft + - apple responses: - '204': - description: Lock released - '400': - description: Invalid lock key + '200': + description: Current access token content: application/json: schema: - $ref: '#/components/schemas/Error' + type: object + properties: + message: + type: string + provider: + type: string + expires_in: + type: integer '401': - description: Missing or invalid credentials + description: Not authenticated content: application/json: schema: $ref: '#/components/schemas/Error' - '403': - description: A non-service credential was supplied or the service key lacks `locks.manage` + '404': + description: Provider not linked content: application/json: schema: $ref: '#/components/schemas/Error' - '429': - description: Project lock request limit exceeded - headers: - Retry-After: - description: Seconds until the current fixed-minute window ends. - schema: - type: integer - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '503': - description: Lock service unavailable - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /storage/{bucketName}/move: - post: - tags: - - Storage Objects - summary: Move/rename an object - operationId: moveStorageObject - security: - - ServiceRoleKey: [] - - AuthUserAccessToken: [] - parameters: - - $ref: '#/components/parameters/BucketName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/StorageMoveRequest' - responses: - '200': - description: Object moved - content: - application/json: - schema: - $ref: '#/components/schemas/StorageObject' - '403': - description: Access denied by storage policy - '429': - $ref: '#/components/responses/BandwidthCapExceeded' - /storage/{bucketName}/copy: - post: - tags: - - Storage Objects - summary: Copy an object - operationId: copyStorageObject - security: - - ServiceRoleKey: [] - - AuthUserAccessToken: [] - parameters: - - $ref: '#/components/parameters/BucketName' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/StorageCopyRequest' - responses: - '201': - description: Object copied - content: - application/json: - schema: - $ref: '#/components/schemas/StorageObject' - '403': - description: Access denied by storage policy - '429': - $ref: '#/components/responses/BandwidthCapExceeded' - /storage/{bucketName}/{path}: + /auth/oauth/{provider}/call-api: post: tags: - - Storage Objects - summary: Upload a file or create resumable session + - OAuth Authentication + summary: Call OAuth provider API description: | - Unified endpoint for file uploads. Behavior depends on Content-Type and headers: - - **Simple Upload (multipart/form-data):** - Upload a complete file in a single request. Best for files under 100MB. + Make an authenticated request to an OAuth provider's API on behalf of the user. + The user's stored access token is automatically used and refreshed if needed. - **Create Resumable Session (application/json):** - Create a session for chunked uploads. Best for large files or unreliable networks. - Requires: `Content-Type: application/json` with body `{"filename": "...", "content_type": "...", "total_size": ...}` + The request is always sent to the provider's fixed API base URL joined with + the caller-supplied `endpoint`. `endpoint` must be a relative path beginning + with `/` (optionally with a query string); it cannot change the target host. + Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are + rejected with `400` so the request can never be redirected to another host. - **Complete Resumable Session:** - Complete a session after all parts are uploaded. - Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header. + Examples of `endpoint`: + - Google userinfo: `/oauth2/v1/userinfo` + - GitHub repositories: `/user/repos` + - Microsoft Graph profile: `/me` - **Resumable Session Ownership:** - A session created with a user access token remains bound to that user. A session - created with an anon key remains bound to that exact anon key. Reuse the same - identity or anon key for part uploads, status, completion, and abort requests; - an ownership mismatch returns `404`. - operationId: uploadStorageObject + The response wraps the provider's raw JSON value with request metadata. + An empty provider body is represented as `data: null`; the envelope + preserves the provider's HTTP status in `status_code`, including errors. + Provider response bodies are limited to 8 MiB after decompression. + Transport failures, invalid JSON (including invalid UTF-8), and oversized + bodies return `502`. Provider redirects to another origin are blocked and + return `400`. + operationId: callOAuthProviderAPI security: - - AnonKey: [] - - ServiceRoleKey: [] - AuthUserAccessToken: [] parameters: - - $ref: '#/components/parameters/BucketName' - - name: path + - name: provider in: path required: true - description: Object path within bucket - schema: - type: string - - name: X-Upload-Session - in: header - required: false - description: Upload session ID (for completing resumable uploads) - schema: - type: string - - name: X-Upload-Complete - in: header - required: false - description: Set to "true" to complete a resumable upload session schema: type: string enum: - - 'true' + - google + - github + - microsoft + - apple requestBody: required: true content: - multipart/form-data: + application/json: schema: type: object required: - - file + - endpoint properties: - file: + endpoint: type: string - format: binary - description: File to upload (simple upload) - application/json: - schema: - $ref: '#/components/schemas/CreateUploadSessionRequest' + description: | + Relative path on the provider's API, beginning with `/`. It is + joined with the provider's fixed base URL; it must not contain a + scheme, host, userinfo, or a leading `//`. + example: /user/repos + method: + type: string + enum: + - GET + - POST + default: GET + description: HTTP method to use + body: + type: object + additionalProperties: true + description: Request body for POST requests responses: '200': - description: Resumable upload completed (when X-Upload-Complete=true) + description: Provider API response content: application/json: schema: - $ref: '#/components/schemas/CompleteUploadSessionResponse' - '201': - description: File uploaded or session created + type: object + description: OAuth provider API response envelope + required: + - provider + - endpoint + - status_code + - data + properties: + provider: + type: string + enum: + - google + - github + - microsoft + - apple + endpoint: + type: string + status_code: + type: integer + minimum: 100 + maximum: 599 + data: + description: Raw provider JSON value, or null when the provider returns no body + nullable: true + '400': + description: | + Invalid request (for example: missing `endpoint`, an `endpoint` that is + not a relative path, or an unsupported HTTP method), or a provider + redirect to another origin. content: application/json: schema: - oneOf: - - $ref: '#/components/schemas/StorageObject' - - $ref: '#/components/schemas/CreateUploadSessionResponse' - '400': - description: | - Bad request. This can occur when: - - MIME type is not in the bucket's allowed_mime_types list - - File exceeds the bucket's configured file_size_limit - - File exceeds the global maximum upload size (5GB) - - Invalid request body or missing required fields - '403': - description: Access denied by storage policy + $ref: '#/components/schemas/Error' + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Resumable upload session not found or not owned by this credential - '413': - description: | - File size exceeds plan-based limits. This occurs when: - - File exceeds the plan-based maximum file size (HOBBY or SUPERAGENT tier) - - Upload would exceed the project's total storage quota - '429': - $ref: '#/components/responses/BandwidthCapExceeded' - put: + description: OAuth provider configuration not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Failed to create the provider API request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '502': + description: Provider transport failure, invalid JSON, or response body larger than 8 MiB + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/anon-keys: + get: tags: - - Storage Objects - summary: Upload a part of a resumable upload + - Anon Keys + summary: List anon keys description: | - Upload a single part of a resumable upload session. - - **Requirements:** - - Part numbers start at 1 - - All parts except the last must be at least 5MB - - Maximum part size is 25MB - - Parts can be uploaded in any order - - Re-uploading a part overwrites the previous upload - - Anonymous sessions must reuse the exact anon key that created the session - operationId: uploadPart + Supports two mutually exclusive pagination modes. Offset mode uses `page` + and `limit` and is the default when neither `cursor` nor `search` is + supplied (first page, default `limit`). Cursor mode uses `cursor` and + `limit`, supports `search` (case-insensitive name match), and returns + `next_cursor`. Sending both `page` and `cursor` (or `page` and `search`) + returns 400. + operationId: listAnonKeys security: - - AnonKey: [] - - ServiceRoleKey: [] - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - $ref: '#/components/parameters/BucketName' - - name: path - in: path - required: true - description: Object path within bucket - schema: - type: string - - name: X-Upload-Session - in: header - required: true - description: Upload session ID - schema: - type: string - - name: X-Part-Number - in: header - required: true - description: Part number (1 to 10000) - schema: - type: integer - minimum: 1 - maximum: 10000 + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + responses: + '200': + description: List of anon keys + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/AnonKey' + total: + type: integer + description: Total number of items matching the query (so the UI can render numbered pages). + has_more: + type: boolean + description: Whether a next page exists. + next_cursor: + type: string + description: Opaque cursor for the next page (cursor pagination only) + prev_cursor: + type: string + description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. + post: + tags: + - Anon Keys + summary: Create anon key + operationId: createAnonKey + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: - application/octet-stream: + application/json: schema: - type: string - format: binary + type: object + required: + - name + properties: + name: + type: string + description: | + Key name for identification. + Can only contain letters, numbers, underscores, and hyphens. + pattern: ^[A-Za-z0-9_-]+$ + minLength: 1 + maxLength: 255 + example: frontend-app + permissions: + type: array + items: + type: string + enum: + - auth.signup + - auth.signin + - auth.refresh + - auth.logout + - auth.password_reset + - auth.confirm_email + - auth.resend_confirmation + - storage.upload + - storage.download + - storage.list + - storage.delete + - realtime.connect + - realtime.subscribe + - realtime.publish + - functions.invoke + description: | + Optional list of permissions for this key. + If not provided, defaults to auth-only permissions: auth.signup, auth.signin, auth.refresh, auth.logout, auth.password_reset, auth.confirm_email, auth.resend_confirmation. + Storage, realtime, and functions permissions must be explicitly added if needed. + example: + - auth.signup + - auth.signin + - auth.refresh + - auth.logout responses: - '200': - description: Part uploaded + '201': + description: Anon key created content: application/json: schema: - $ref: '#/components/schemas/UploadSessionPart' - '400': - description: Invalid part number or part data - '403': - description: Access denied - '404': - description: Session not found or not owned by this credential + $ref: '#/components/schemas/AnonKey' + /projects/{id}/anon-keys/{keyId}: get: tags: - - Storage Objects - summary: Download a file or get upload session status - description: | - Download a file, or get the status of a resumable upload session. - - **File Download (default):** - Downloads the file at the specified path. - - **Session Status (with X-Upload-Session header):** - Returns the status of a resumable upload session, including which parts have been uploaded. - Anonymous sessions must reuse the exact anon key that created the session. - operationId: downloadStorageObject + - Anon Keys + summary: Get anon key + description: Get details of a specific anon key + operationId: getAnonKey security: - - AnonKey: [] - - ServiceRoleKey: [] - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - $ref: '#/components/parameters/BucketName' - - name: path + - $ref: '#/components/parameters/ProjectId' + - name: keyId in: path required: true - description: Object path within bucket - schema: - type: string - - name: Range - in: header - required: false - description: | - HTTP Range header for partial downloads. - Format: bytes=start-end or bytes=start- - Examples: bytes=0-1023, bytes=1000- - schema: - type: string - pattern: ^bytes=\d+-\d*$ - - name: X-Upload-Session - in: header - required: false - description: Upload session ID (to get session status instead of downloading) schema: type: string + format: uuid responses: '200': - description: File content or session status - headers: - Content-Type: - schema: - type: string - Content-Length: - schema: - type: integer - ETag: - schema: - type: string + description: Anon key details content: - application/octet-stream: - schema: - type: string - format: binary application/json: schema: - $ref: '#/components/schemas/UploadSessionStatusResponse' - '206': - description: Partial content (range request) - '400': - description: Invalid Range header format - '403': - description: Access denied by storage policy + $ref: '#/components/schemas/AnonKey' '404': - description: Object or session not found, or session not owned by this credential - '429': - $ref: '#/components/responses/BandwidthCapExceeded' + description: Key not found delete: tags: - - Storage Objects - summary: Delete a file or abort upload session - description: | - Delete a file, or abort a resumable upload session. - - **File Delete (default):** - Deletes the file at the specified path. - - **Abort Session (with X-Upload-Session header):** - Aborts a resumable upload session and cleans up any uploaded parts. - Anonymous sessions must reuse the exact anon key that created the session. - operationId: deleteStorageObject + - Anon Keys + summary: Revoke anon key + description: Revokes key - it will immediately stop working + operationId: revokeAnonKey security: - - AnonKey: [] - - ServiceRoleKey: [] - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - $ref: '#/components/parameters/BucketName' - - name: path + - $ref: '#/components/parameters/ProjectId' + - name: keyId in: path required: true - description: Object path within bucket - schema: - type: string - - name: X-Upload-Session - in: header - required: false - description: Upload session ID (to abort session instead of deleting file) schema: type: string + format: uuid responses: - '200': - description: Object deleted or session aborted + '204': + description: Key revoked + '401': + description: Unauthorized '403': - description: Access denied by storage policy + description: Forbidden '404': - description: Object or session not found, or session not owned by this credential - '429': - $ref: '#/components/responses/BandwidthCapExceeded' - /storage/{bucketName}/{path}/visibility: - patch: - tags: - - Storage Objects - summary: Update file visibility (public/private) - description: | - Change whether a file is publicly accessible. Only the file owner or a service key can change visibility. - If the bucket defines UPDATE policies, the owner must also satisfy one of them. - - - Public files can be downloaded with just an anon key (no user authentication required) - - Private files (default) require authentication and must pass policy checks - - All downloads go through the Volcano API - there is no direct access to the underlying store - operationId: updateStorageObjectVisibility + description: Key not found + '409': + description: Cannot delete the project's default anon key + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/anon-keys/{keyId}/regenerate: + post: + tags: + - Anon Keys + summary: Regenerate anon key + description: Generate new JWT value for existing key + operationId: regenerateAnonKey security: - - ServiceRoleKey: [] - - AuthUserAccessToken: [] + - UserToken: [] + - ProjectAccessToken: [] parameters: - - $ref: '#/components/parameters/BucketName' - - name: path + - $ref: '#/components/parameters/ProjectId' + - name: keyId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Key regenerated + content: + application/json: + schema: + $ref: '#/components/schemas/AnonKey' + /projects/{id}/anon-keys/{keyId}/set-default: + post: + tags: + - Anon Keys + summary: Set default anon key + description: Promotes the given key to the project's configured default. At most one key per project can be default. + operationId: setDefaultAnonKey + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: keyId in: path required: true - description: Object path within bucket schema: type: string + format: uuid + responses: + '200': + description: Key set as default + content: + application/json: + schema: + $ref: '#/components/schemas/AnonKey' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Anon key not found + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/access-tokens: + get: + tags: + - Project Access Tokens + summary: List a project's access tokens + description: | + Lists the project's access tokens, newest first. Secrets are never + returned: only a hash is stored, so a token's value exists solely in the + response to the create call. + + Only tokens that can still authenticate are returned by default, so + revoked and expired ones are hidden. Pass `include_revoked=true` to see + them, which is how you find out what a key did before it stopped working. + + Requires a platform token. A project access token cannot manage project + access tokens, so a leaked credential cannot enumerate or replace itself. + operationId: listProjectAccessTokens + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Search' + - name: include_revoked + in: query + required: false + description: | + Include tokens that can no longer authenticate — both revoked and + expired ones. + schema: + type: boolean + default: false + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedProjectAccessTokens' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - not the project owner, or a project access token was used + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Project not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + tags: + - Project Access Tokens + summary: Create a project access token + description: | + Creates a project access token and returns its secret. + + The secret is in this response and nowhere else. Only its hash is + stored, so it cannot be retrieved, displayed, or recovered later — save + it when you create it. + + The name must be unique within the project, so a retry cannot mint a + second credential. It cannot recover the first one either. A retry that + returns `409` with code `access_token_name_exists` means the original + create committed and its secret is unrecoverable: list the project's + tokens, revoke the one holding that name, and create it again. + + Requires a platform token. + operationId: createProjectAccessToken + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/StorageVisibilityRequest' + $ref: '#/components/schemas/CreateProjectAccessTokenRequest' responses: - '200': - description: Visibility updated + '201': + description: Token created - save the secret now, it cannot be retrieved again content: application/json: schema: - $ref: '#/components/schemas/StorageObject' + $ref: '#/components/schemas/CreatedProjectAccessToken' + '400': + description: Bad request - invalid name, scope, or expiry + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '403': - description: Not the file owner or denied by the bucket's UPDATE policies + description: Forbidden - not the project owner, or a project access token was used + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Object not found - /public/{projectId}/{bucketName}/{path}: + description: Project not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: | + Duplicate name, token limit reached, or the project is being + deleted. Tell them apart with `code`, which is one of + `access_token_name_exists`, `access_token_limit_reached`, or + `project_deleting` — the message text is not a contract. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/access-tokens/usage: get: tags: - - Storage Objects - summary: Download a public file (no authentication required) + - Project Access Tokens + summary: Per-day request counts for every access token in a project description: | - Download a file that has been marked as public. This endpoint requires NO authentication. - - **Access Requirements:** - - The file must have `is_public: true` set via the visibility endpoint - - Private files will return 403 Forbidden - - **Use Cases:** - - Shareable public URLs for profile pictures, public documents, etc. - - Embedding public files on external websites - - Direct linking without requiring SDK or authentication + Returns a zero-filled daily series of request counts for each of the + project's access tokens, oldest first. Every day in the window is + present, so a gap reads as zero rather than missing. - **URL Format:** - ``` - GET /public/{projectId}/{bucketName}/{path} - ``` + Revoked tokens are included, because the traffic they made before + revocation is usually the reason you are looking. - **Example:** - ``` - https://api.volcano.dev/public/abc123/avatars/user-photo.jpg - ``` + `days` defaults to 30 and is capped at 60, which is also how long per-day + counts are retained — a longer window cannot be answered. - **CORS:** - This endpoint allows all origins since the file is already public. - operationId: downloadPublicFile + A platform token sees every token in the project. A project access token + sees only its own row, so it can watch its own traffic without being + able to enumerate the project's other credentials by name. + operationId: listProjectAccessTokensUsage + security: + - UserToken: [] + - ProjectAccessToken: [] parameters: - - name: projectId - in: path - required: true - description: Project ID - schema: - type: string - format: uuid - - $ref: '#/components/parameters/BucketName' - - name: path - in: path - required: true - description: Object path within bucket + - $ref: '#/components/parameters/ProjectId' + - name: days + in: query + required: false + description: Number of trailing days to return (1-60, default 30). schema: - type: string + type: integer + minimum: 1 + maximum: 60 + default: 30 responses: '200': - description: File content + description: Successful response content: - '*/*': + application/json: schema: - type: string - format: binary - '206': - description: Partial content (range request) + type: array + items: + $ref: '#/components/schemas/ProjectAccessTokenUsage' + '400': + description: Bad request - invalid window + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - not the project owner + content: + application/json: + schema: + $ref: '#/components/schemas/Error' '404': - description: Not found (file doesn't exist or is not public) - '429': - $ref: '#/components/responses/BandwidthCapExceeded' - /health: + description: Project not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/access-tokens/{tokenId}: get: tags: - - System - summary: Health check endpoint - description: Returns server health status. Used for load balancer and monitoring checks. - operationId: healthCheck + - Project Access Tokens + summary: Get a project access token + description: | + Returns one token's metadata. Never its secret, which is not stored in a + recoverable form. + + Requires a platform token. + operationId: getProjectAccessToken + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/TokenId' responses: '200': - description: Server is healthy + description: Successful response content: - text/plain: + application/json: schema: - type: string - example: OK -components: - securitySchemes: - AnonKey: - type: http - scheme: bearer - bearerFormat: JWT - description: | - Project-specific public key for frontend authentication. - Required for signup, signin, refresh, and logout endpoints. - Get from Project Settings → Authentication → Anon Keys. - Safe to expose in frontend code (scoped to project, limited permissions). - AuthUserAccessToken: - type: http - scheme: bearer - bearerFormat: JWT - description: | - Auth user access token obtained from signup/signin. - Used for authenticated function invocation and user profile access. - Functions invoked with access tokens receive user context in event.__volcano_auth. - Expires after configured lifetime (default: 1 hour). - ServiceRoleKey: - type: http - scheme: bearer - bearerFormat: JWT - description: | - Service role key for admin operations. - **WARNING:** Bypasses Row-Level Security - backend use only! - Create via POST /projects/{id}/service-keys. - Used for function invocation with full database access. - UserToken: - type: http - scheme: bearer - bearerFormat: JWT + $ref: '#/components/schemas/ProjectAccessToken' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - not the project owner, or a project access token was used + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Token not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + tags: + - Project Access Tokens + summary: Revoke a project access token description: | - Platform user token from the Management API. - Required for project management operations. - Obtain via POST /tokens in Management API (port 8001). - parameters: - BackupName: - name: backupName - in: path - required: true - schema: - type: string - minLength: 1 - maxLength: 128 + Revokes the token. It stops authenticating immediately in the region + handling this call and within seconds across Volcano's other regions. + + The record is kept rather than deleted, so the token's name, prefix, last + use, and request history stay available — which is what you need if you + are revoking because a secret leaked. Revoking an already-revoked token + succeeds. + + Revoking does not undo anything the token already did. Treat whatever it + could reach as exposed and rotate accordingly. + + Requires a platform token. + operationId: revokeProjectAccessToken + security: + - UserToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/TokenId' + responses: + '204': + description: Token revoked + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - not the project owner, or a project access token was used + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Token not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: Conflict - the project is being deleted + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/access-tokens/{tokenId}/usage: + get: + tags: + - Project Access Tokens + summary: Per-day request counts for one access token description: | - Backup name, unique within the database, exactly as returned by the list - endpoint. + Returns a zero-filled daily series of request counts for a single token, + oldest first, so the response always has exactly `days` entries. - Deliberately looser than the names you can create: a backup made by a - schedule is named for you, so reading or deleting one accepts any name a - backup can have. - BranchName: - name: branchName - in: path - required: true - schema: - type: string - pattern: ^[a-z0-9_]+$ - maxLength: 64 - description: Branch name (unique within the parent database, lowercase letters, numbers, and underscores only) - BucketName: - name: bucketName - in: path - required: true - schema: - type: string - pattern: ^[a-zA-Z0-9_-]+$ - minLength: 1 - maxLength: 64 - description: Storage bucket name - Cursor: - name: cursor - in: query - required: false - schema: - type: string + `days` defaults to 30 and is capped at 60, matching how long per-day + counts are retained. + + A project access token may read only its own usage; asking for another + token's returns `403`. A platform token may read any token in the + project. + operationId: getProjectAccessTokenUsage + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/TokenId' + - name: days + in: query + required: false + description: Number of trailing days to return (1-60, default 30). + schema: + type: integer + minimum: 1 + maximum: 60 + default: 30 + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectAccessTokenUsage' + '400': + description: Bad request - invalid window + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized - invalid or missing token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden - not the project owner + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Token not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/service-keys: + get: + tags: + - Service Keys + summary: List service keys (paginated) description: | - Opaque keyset pagination cursor from a previous response's `next_cursor` - — pages forward. Mutually exclusive with `page` and `ending_before`; - combining them returns 400. When supplied, the request's `search` and - `limit` must match the values bound to the cursor or the request returns 400. - EndingBefore: - name: ending_before - in: query - required: false - schema: - type: string + List all service role keys for a project with pagination. + + **WARNING:** Service keys bypass RLS - for backend/admin use only! + operationId: listServiceKeys + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Page' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + responses: + '200': + description: Paginated list of service keys + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedServiceKeys' + post: + tags: + - Service Keys + summary: Create service key description: | - Opaque keyset pagination cursor from a previous response's `prev_cursor` - — pages backward (the page immediately preceding this cursor). Mutually - exclusive with `page` and `cursor`; combining them returns 400. `search` - and `limit` must match the values bound to the cursor or the request - returns 400. - DatabaseName: - name: databaseName - in: path - required: true - schema: - type: string - pattern: ^[a-z0-9_]+$ - maxLength: 64 - description: Database name (unique within project, lowercase letters, numbers, and underscores only) - DeploymentId: - name: deploymentId - in: path - required: true - schema: - type: string - format: uuid - description: Frontend deployment ID - FrontendId: - name: frontendId - in: path - required: true - schema: - type: string - format: uuid - description: Frontend ID - FunctionId: - name: functionId - in: path - required: true - schema: - type: string - format: uuid - description: Function ID - DurableFunctionId: - name: functionId - in: path - required: true - schema: - type: string - description: Durable function ID, or its name within the project - DurableExecutionId: - name: executionId - in: path - required: true - schema: - type: string - format: uuid - description: Durable execution ID - Limit: - name: limit - in: query - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 10 - description: Number of items per page (max 100) - LockKey: - name: key - in: path - required: true - description: Project-local lock name. - schema: - type: string - minLength: 1 - maxLength: 128 - pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$ - LockToken: - name: X-Volcano-Lock-Token - in: header - required: true - description: Opaque UUID generated once by the caller and retained for the lease lifetime. - schema: - type: string - format: uuid - LockRequestId: - name: X-Volcano-Request-Id - in: header - required: true - description: | - UUID correlating this request across client and server logs. Repeat safety comes from - the lock token, so a retry under a reused request ID still counts against the quota. - schema: - type: string - format: uuid - DeploymentOperation: - name: operation - in: query - required: false - description: Restrict a deployment feed to one kind of operation. - schema: - type: string - enum: - - deploy - - redeploy - - update - - delete - DeploymentOwnerId: - name: owner_id - in: query - required: false - description: | - The user who owns the projects whose deployments to return - (`projects.user_id`). This is ownership, not the actor that started the - deployment — see `initiated_by_user_id` for that. Not a UUID: platform - user ids are opaque strings. - schema: - type: string - maxLength: 255 - DeploymentOrder: - name: order - in: query - required: false - description: | - Sort key and direction. `created_at.desc` (default) is the feed order. - `completed_at.asc` orders finished attempts by completion, oldest first, - and excludes attempts that never completed. - schema: - type: string - enum: - - created_at.desc - - completed_at.asc - default: created_at.desc - DeploymentResourceType: - name: resource_type - in: query - required: false + Create a new service role key for admin operations. + + **WARNING:** Service keys bypass all RLS policies! + Store securely and NEVER expose in frontend code. + operationId: createServiceKey + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + properties: + name: + type: string + description: | + Descriptive name for the key (e.g., "admin-dashboard", "background-jobs"). + Can only contain letters, numbers, underscores, and hyphens. + pattern: ^[A-Za-z0-9_-]+$ + minLength: 1 + maxLength: 255 + example: admin-dashboard + permissions: + type: array + items: + type: string + description: | + Optional least-privilege scope for the key. When omitted, empty, or + containing only blank strings, the key is granted full access (["*"]) + for backward compatibility. Provide an explicit list (e.g. + ["functions.invoke", "locks.manage"]) to restrict the key; "*" + grants everything. Scope enforcement applies to function invocation, + storage object operations, and project locks. + example: + - functions.invoke + - locks.manage + responses: + '201': + description: Service key created - save the key_value immediately! + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceKey' + '409': + description: Key with this name already exists + /projects/{id}/service-keys/{keyId}: + get: + tags: + - Service Keys + summary: Get service key + description: Get details of a specific service key + operationId: getServiceKey + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: keyId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Service key details + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceKey' + '404': + description: Key not found + delete: + tags: + - Service Keys + summary: Delete service key description: | - Restrict a deployment feed to a single resource type. Omit to return - both Function and Frontend deployments. - schema: - type: string - enum: - - function - - frontend - DeploymentStatus: - name: status - in: query - required: false - description: Restrict a deployment feed to attempts in one status. - schema: - type: string - enum: - - queued - - provisioning - - active - - degraded - - failed - - superseded - - deleting - - deleted - Offset: - name: offset - in: query - required: false - schema: - type: integer - minimum: 0 - default: 0 + Permanently delete a service key. + Any services using this key will immediately lose access. + operationId: deleteServiceKey + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: keyId + in: path + required: true + schema: + type: string + format: uuid + responses: + '204': + description: Key deleted + /projects/{id}/service-keys/{keyId}/regenerate: + post: + tags: + - Service Keys + summary: Regenerate service key description: | - Bounded row offset past the keyset anchor named by `cursor` (forward) or - `ending_before` (backward) — the hybrid jump. Seek to the anchor, then - skip this many rows within. Used for numbered jump-to-page: from the - current page, seek to its next/prev cursor and offset the remaining - pages. Only honored on the cursor pagination path; ignored otherwise. - Page: - name: page - in: query - required: false - schema: - type: integer - minimum: 1 + Generate new JWT value for existing key. + The old key stops working within a few seconds. + Update your backend services with the new key before regenerating in production. + operationId: regenerateServiceKey + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: keyId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Key regenerated - save the new key_value immediately! + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceKey' + /projects/{id}/storage/buckets: + get: + tags: + - Storage Buckets + summary: List all storage buckets in a project description: | - Page number (1-indexed) for offset pagination. Declares no schema - default so the request validator does not inject one: handlers that omit - `page` see it unset (nil) and default to 1 in code, while cursor-first - endpoints (e.g. the project deployments feed) can detect its absence to - stay in keyset/search mode. Supplying `page` selects offset pagination. - ProjectId: - name: id - in: path - required: true - schema: - type: string - format: uuid - description: Project ID - Search: - name: search - in: query - required: false - schema: - type: string - maxLength: 256 - description: | - Case-insensitive substring match on the resource `name`. See the - endpoint description for supported pagination modes. - RestoreId: - name: restoreId - in: path - required: true - schema: - type: string - format: uuid - description: Database restore ID - SchedulerId: - name: schedulerId - in: path - required: true - schema: - type: string - format: uuid - description: Function scheduler ID - VariableName: - name: name - in: path - required: true - schema: - type: string - minLength: 1 - maxLength: 256 - pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ - description: Variable name - responses: - BandwidthCapExceeded: - description: | - The platform user exceeded their billing-cycle bandwidth allowance (aggregate - ingress + egress across owned projects). Enforcement is eventual: - requests are rejected until the allowance increases or the next - anniversary cycle begins. - content: - application/json: + With no pagination params, returns the full bucket list as a bare array + (legacy). Supplying `cursor`, `ending_before`, `search`, or `limit` + switches to keyset (cursor) pagination and returns a paginated envelope + with `next_cursor`/`prev_cursor` and a filtered `total`. + operationId: listStorageBuckets + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + responses: + '200': + description: | + Either the full bucket list (bare array, legacy) or a paginated + envelope when cursor pagination is requested. + content: + application/json: + schema: + oneOf: + - type: array + items: + $ref: '#/components/schemas/StorageBucket' + - $ref: '#/components/schemas/PaginatedStorageBuckets' + post: + tags: + - Storage Buckets + summary: Create a new storage bucket + operationId: createStorageBucket + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateStorageBucketRequest' + responses: + '201': + description: Bucket created + content: + application/json: + schema: + $ref: '#/components/schemas/StorageBucket' + '409': + description: Bucket already exists + /projects/{id}/storage/buckets/{bucketName}: + get: + tags: + - Storage Buckets + summary: Get storage bucket by name + operationId: getStorageBucket + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/BucketName' + responses: + '200': + description: Bucket details + content: + application/json: + schema: + $ref: '#/components/schemas/StorageBucket' + '404': + description: Bucket not found + patch: + tags: + - Storage Buckets + summary: Update storage bucket settings + operationId: updateStorageBucket + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/BucketName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateStorageBucketRequest' + responses: + '200': + description: Bucket updated + content: + application/json: + schema: + $ref: '#/components/schemas/StorageBucket' + delete: + tags: + - Storage Buckets + summary: Delete storage bucket and all objects + operationId: deleteStorageBucket + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/BucketName' + responses: + '200': + description: Bucket deleted + /projects/{id}/storage/buckets/{bucketName}/policies: + get: + tags: + - Storage Policies + summary: List storage policies for a bucket + operationId: listStoragePolicies + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/BucketName' + responses: + '200': + description: List of policies + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/StoragePolicy' + post: + tags: + - Storage Policies + summary: Create a storage policy + operationId: createStoragePolicy + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/BucketName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateStoragePolicyRequest' + responses: + '201': + description: Policy created + content: + application/json: + schema: + $ref: '#/components/schemas/StoragePolicy' + /projects/{id}/storage/buckets/{bucketName}/policies/{policyId}: + delete: + tags: + - Storage Policies + summary: Delete a storage policy + operationId: deleteStoragePolicy + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - $ref: '#/components/parameters/BucketName' + - name: policyId + in: path + required: true schema: - $ref: '#/components/schemas/Error' - DatabaseQueryCapExceeded: + type: string + format: uuid + responses: + '200': + description: Policy deleted + /projects/{id}/storage/objects: + get: + tags: + - Storage Admin + summary: List all storage objects in a project description: | - The query was rejected by a billing-cycle allowance: either the owning - platform user's bandwidth allowance (aggregate ingress + egress across - owned projects) or their database-request allowance. Enforcement is - eventual: queries are rejected until the allowance increases or the - next anniversary cycle begins. The error message identifies the resource. - content: - application/json: + Returns a paginated list of all storage objects across all buckets in the project. + Supports filtering by owner and pagination. + operationId: listStorageObjectsAdmin + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + - name: owner_id + in: query + description: Filter by owner user ID schema: - $ref: '#/components/schemas/Error' - DatabaseBranchQueryUnavailable: - description: | - The branch exists but cannot serve queries: it is still provisioning, - being reset, expired, or its parent is being restored. Distinct from - `404` so a caller waiting on a branch can tell it apart from a typo. - content: - application/json: + type: string + format: uuid + - name: page + in: query + description: Page number (1-based) schema: - $ref: '#/components/schemas/Error' - schemas: + type: integer + default: 1 + minimum: 1 + - name: limit + in: query + description: Items per page + schema: + type: integer + default: 50 + minimum: 1 + maximum: 100 + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/EndingBefore' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/Search' + responses: + '200': + description: Paginated list of storage objects + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/StorageObjectWithBucket' + page: + type: integer + limit: + type: integer + total: + type: integer + has_more: + type: boolean + next_cursor: + type: string + description: Opaque cursor for the next page (cursor pagination only) + prev_cursor: + type: string + description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`. + /projects/{id}/storage/stats: + get: + tags: + - Storage Admin + summary: Get storage statistics for a project + description: Returns aggregate storage statistics including bucket count, object count, and total size. + operationId: getStorageStats + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + responses: + '200': + description: Storage statistics + content: + application/json: + schema: + $ref: '#/components/schemas/StorageStats' + /projects/{id}/realtime/config: + get: + tags: + - Realtime + summary: Get realtime configuration for a project + description: Returns the realtime configuration including enabled features and limits. + operationId: getRealtimeConfig + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + responses: + '200': + description: Realtime configuration + content: + application/json: + schema: + $ref: '#/components/schemas/RealtimeConfig' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Project not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + put: + tags: + - Realtime + summary: Update realtime configuration for a project + description: Updates realtime settings including feature toggles and limits. + operationId: updateRealtimeConfig + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateRealtimeConfigRequest' + responses: + '200': + description: Updated realtime configuration + content: + application/json: + schema: + $ref: '#/components/schemas/RealtimeConfig' + '400': + description: Invalid configuration values + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /projects/{id}/realtime/stats: + get: + tags: + - Realtime + summary: Get realtime statistics for a project + description: Returns realtime usage statistics including connection counts and subscribed tables. + operationId: getRealtimeStats + security: + - UserToken: [] + - ProjectAccessToken: [] + parameters: + - $ref: '#/components/parameters/ProjectId' + responses: + '200': + description: Realtime statistics + content: + application/json: + schema: + $ref: '#/components/schemas/RealtimeStats' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /storage/{bucketName}: + get: + tags: + - Storage Objects + summary: List objects in a bucket + operationId: listStorageObjects + security: + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + - name: prefix + in: query + description: Filter objects by path prefix + schema: + type: string + - name: limit + in: query + description: Maximum objects to return + schema: + type: integer + default: 50 + maximum: 1000 + - name: cursor + in: query + description: Pagination cursor + schema: + type: string + responses: + '200': + description: List of objects + content: + application/json: + schema: + $ref: '#/components/schemas/StorageListResponse' + '403': + description: Access denied by storage policy + '429': + $ref: '#/components/responses/BandwidthCapExceeded' + /locks/{key}/lease: + post: + tags: + - Locks + summary: Acquire a project lock + description: | + Acquires a project-scoped lease using the project embedded in the service-role key. + The caller must hold the `locks.manage` permission. Repeating the request with the + same lock token is idempotent and resets that lease to the requested TTL. A different + live owner receives `409 lock_held`; a caller whose own lease already lapsed receives + `409 lock_ownership_lost`. + operationId: acquireProjectLock + security: + - ServiceRoleKey: [] + parameters: + - $ref: '#/components/parameters/LockKey' + - $ref: '#/components/parameters/LockToken' + - $ref: '#/components/parameters/LockRequestId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectLockLeaseRequest' + responses: + '201': + description: Lease acquired + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectLockLease' + '400': + description: Invalid lock key, token, or TTL + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Missing or invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: A non-service credential was supplied or the service key lacks `locks.manage` + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: | + The lock is held by another live lease (`lock_held`), or the caller's own lease + lapsed and is not yet reclaimable (`lock_ownership_lost`). + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Project lock request limit exceeded + headers: + Retry-After: + description: Seconds until the current fixed-minute window ends. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Lock service unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + patch: + tags: + - Locks + summary: Renew a project lock + description: | + Renews a lease owned by the supplied lock token. The request must arrive + more than one second before `expires_at`; this safety margin prevents + clock skew between regional API instances from resurrecting an expired + lease. + operationId: renewProjectLock + security: + - ServiceRoleKey: [] + parameters: + - $ref: '#/components/parameters/LockKey' + - $ref: '#/components/parameters/LockToken' + - $ref: '#/components/parameters/LockRequestId' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectLockLeaseRequest' + responses: + '200': + description: Lease renewed + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectLockLease' + '400': + description: Invalid lock key, token, or TTL + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Missing or invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: A non-service credential was supplied or the service key lacks `locks.manage` + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: The lease expired or is owned by another token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Project lock request limit exceeded + headers: + Retry-After: + description: Seconds until the current fixed-minute window ends. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Lock service unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + tags: + - Locks + summary: Release a project lock + description: Releases a lease only when the supplied lock token still owns it. + operationId: releaseProjectLock + security: + - ServiceRoleKey: [] + parameters: + - $ref: '#/components/parameters/LockKey' + - $ref: '#/components/parameters/LockToken' + - $ref: '#/components/parameters/LockRequestId' + responses: + '204': + description: Lease released + '400': + description: Invalid lock key or token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Missing or invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: A non-service credential was supplied or the service key lacks `locks.manage` + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '409': + description: The lease is owned by another token + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Project lock request limit exceeded + headers: + Retry-After: + description: Seconds until the current fixed-minute window ends. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Lock service unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /locks/{key}: + get: + tags: + - Locks + summary: Read a project lock + description: | + Reports whether the lock is currently held, when its lease expires, and the + holder's fencing token. `held` follows takeover eligibility rather than raw + expiry, so `held: false` means an acquire would succeed now. No lock token is + required, making this usable for monitoring and recovery. + operationId: getProjectLock + security: + - ServiceRoleKey: [] + parameters: + - $ref: '#/components/parameters/LockKey' + - $ref: '#/components/parameters/LockRequestId' + responses: + '200': + description: Current lock state + content: + application/json: + schema: + $ref: '#/components/schemas/ProjectLockState' + '400': + description: Invalid lock key + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Missing or invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: A non-service credential was supplied or the service key lacks `locks.manage` + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Project lock request limit exceeded + headers: + Retry-After: + description: Seconds until the current fixed-minute window ends. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Lock service unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + tags: + - Locks + summary: Force release a project lock + description: | + Drops the lease whatever token holds it, for recovering a lock whose holder + died without releasing. Use `DELETE /locks/{key}/lease` for normal release. + + This breaks mutual exclusion by itself: the previous holder keeps working + until its own renewal fails. Guard the protected resource with the lease's + `fencing_token`, which the next acquisition raises, so a write from the + displaced holder can be rejected. Succeeds when the lock is already absent. + operationId: forceReleaseProjectLock + security: + - ServiceRoleKey: [] + parameters: + - $ref: '#/components/parameters/LockKey' + - $ref: '#/components/parameters/LockRequestId' + responses: + '204': + description: Lock released + '400': + description: Invalid lock key + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Missing or invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: A non-service credential was supplied or the service key lacks `locks.manage` + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Project lock request limit exceeded + headers: + Retry-After: + description: Seconds until the current fixed-minute window ends. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Lock service unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /storage/{bucketName}/move: + post: + tags: + - Storage Objects + summary: Move/rename an object + operationId: moveStorageObject + security: + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/StorageMoveRequest' + responses: + '200': + description: Object moved + content: + application/json: + schema: + $ref: '#/components/schemas/StorageObject' + '403': + description: Access denied by storage policy + '429': + $ref: '#/components/responses/BandwidthCapExceeded' + /storage/{bucketName}/copy: + post: + tags: + - Storage Objects + summary: Copy an object + operationId: copyStorageObject + security: + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/StorageCopyRequest' + responses: + '201': + description: Object copied + content: + application/json: + schema: + $ref: '#/components/schemas/StorageObject' + '403': + description: Access denied by storage policy + '429': + $ref: '#/components/responses/BandwidthCapExceeded' + /storage/{bucketName}/{path}: + post: + tags: + - Storage Objects + summary: Upload a file or create resumable session + description: | + Unified endpoint for file uploads. Behavior depends on Content-Type and headers: + + **Simple Upload (multipart/form-data):** + Upload a complete file in a single request. Best for files under 100MB. + + **Create Resumable Session (application/json):** + Create a session for chunked uploads. Best for large files or unreliable networks. + Requires: `Content-Type: application/json` with body `{"filename": "...", "content_type": "...", "total_size": ...}` + + **Complete Resumable Session:** + Complete a session after all parts are uploaded. + Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header. + + **Resumable Session Ownership:** + A session created with a user access token remains bound to that user. A session + created with an anon key remains bound to that exact anon key. Reuse the same + identity or anon key for part uploads, status, completion, and abort requests; + an ownership mismatch returns `404`. + operationId: uploadStorageObject + security: + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + - name: path + in: path + required: true + description: Object path within bucket + schema: + type: string + - name: X-Upload-Session + in: header + required: false + description: Upload session ID (for completing resumable uploads) + schema: + type: string + - name: X-Upload-Complete + in: header + required: false + description: Set to "true" to complete a resumable upload session + schema: + type: string + enum: + - 'true' + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: + - file + properties: + file: + type: string + format: binary + description: File to upload (simple upload) + application/json: + schema: + $ref: '#/components/schemas/CreateUploadSessionRequest' + responses: + '200': + description: Resumable upload completed (when X-Upload-Complete=true) + content: + application/json: + schema: + $ref: '#/components/schemas/CompleteUploadSessionResponse' + '201': + description: File uploaded or session created + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/StorageObject' + - $ref: '#/components/schemas/CreateUploadSessionResponse' + '400': + description: | + Bad request. This can occur when: + - MIME type is not in the bucket's allowed_mime_types list + - File exceeds the bucket's configured file_size_limit + - File exceeds the global maximum upload size (5GB) + - Invalid request body or missing required fields + '403': + description: Access denied by storage policy + '404': + description: Resumable upload session not found or not owned by this credential + '413': + description: | + File size exceeds plan-based limits. This occurs when: + - File exceeds the plan-based maximum file size (HOBBY or SUPERAGENT tier) + - The account on the HOBBY plan holds its file-storage allowance. + Enforcement is eventual: uploads are accepted until Volcano's + next allowance check sees the account at its allowance + '429': + $ref: '#/components/responses/BandwidthCapExceeded' + put: + tags: + - Storage Objects + summary: Upload a part of a resumable upload + description: | + Upload a single part of a resumable upload session. + + **Requirements:** + - Part numbers start at 1 + - All parts except the last must be at least 5MB + - Maximum part size is 25MB + - Parts can be uploaded in any order + - Re-uploading a part overwrites the previous upload + - Anonymous sessions must reuse the exact anon key that created the session + operationId: uploadPart + security: + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + - name: path + in: path + required: true + description: Object path within bucket + schema: + type: string + - name: X-Upload-Session + in: header + required: true + description: Upload session ID + schema: + type: string + - name: X-Part-Number + in: header + required: true + description: Part number (1 to 10000) + schema: + type: integer + minimum: 1 + maximum: 10000 + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + '200': + description: Part uploaded + content: + application/json: + schema: + $ref: '#/components/schemas/UploadSessionPart' + '400': + description: Invalid part number or part data + '403': + description: Access denied + '404': + description: Session not found or not owned by this credential + get: + tags: + - Storage Objects + summary: Download a file or get upload session status + description: | + Download a file, or get the status of a resumable upload session. + + **File Download (default):** + Downloads the file at the specified path. + + **Session Status (with X-Upload-Session header):** + Returns the status of a resumable upload session, including which parts have been uploaded. + Anonymous sessions must reuse the exact anon key that created the session. + operationId: downloadStorageObject + security: + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + - name: path + in: path + required: true + description: Object path within bucket + schema: + type: string + - name: Range + in: header + required: false + description: | + HTTP Range header for partial downloads. + Format: bytes=start-end or bytes=start- + Examples: bytes=0-1023, bytes=1000- + schema: + type: string + pattern: ^bytes=\d+-\d*$ + - name: X-Upload-Session + in: header + required: false + description: Upload session ID (to get session status instead of downloading) + schema: + type: string + responses: + '200': + description: File content or session status + headers: + Content-Type: + schema: + type: string + Content-Length: + schema: + type: integer + ETag: + schema: + type: string + content: + application/octet-stream: + schema: + type: string + format: binary + application/json: + schema: + $ref: '#/components/schemas/UploadSessionStatusResponse' + '206': + description: Partial content (range request) + '400': + description: Invalid Range header format + '403': + description: Access denied by storage policy + '404': + description: Object or session not found, or session not owned by this credential + '429': + $ref: '#/components/responses/BandwidthCapExceeded' + delete: + tags: + - Storage Objects + summary: Delete a file or abort upload session + description: | + Delete a file, or abort a resumable upload session. + + **File Delete (default):** + Deletes the file at the specified path. + + **Abort Session (with X-Upload-Session header):** + Aborts a resumable upload session and cleans up any uploaded parts. + Anonymous sessions must reuse the exact anon key that created the session. + operationId: deleteStorageObject + security: + - AnonKey: [] + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + - name: path + in: path + required: true + description: Object path within bucket + schema: + type: string + - name: X-Upload-Session + in: header + required: false + description: Upload session ID (to abort session instead of deleting file) + schema: + type: string + responses: + '200': + description: Object deleted or session aborted + '403': + description: Access denied by storage policy + '404': + description: Object or session not found, or session not owned by this credential + '429': + $ref: '#/components/responses/BandwidthCapExceeded' + /storage/{bucketName}/{path}/visibility: + patch: + tags: + - Storage Objects + summary: Update file visibility (public/private) + description: | + Change whether a file is publicly accessible. Only the file owner or a service key can change visibility. + If the bucket defines UPDATE policies, the owner must also satisfy one of them. + + - Public files can be downloaded with just an anon key (no user authentication required) + - Private files (default) require authentication and must pass policy checks + - All downloads go through the Volcano API - there is no direct access to the underlying store + operationId: updateStorageObjectVisibility + security: + - ServiceRoleKey: [] + - AuthUserAccessToken: [] + parameters: + - $ref: '#/components/parameters/BucketName' + - name: path + in: path + required: true + description: Object path within bucket + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/StorageVisibilityRequest' + responses: + '200': + description: Visibility updated + content: + application/json: + schema: + $ref: '#/components/schemas/StorageObject' + '403': + description: Not the file owner or denied by the bucket's UPDATE policies + '404': + description: Object not found + /public/{projectId}/{bucketName}/{path}: + get: + tags: + - Storage Objects + summary: Download a public file (no authentication required) + description: | + Download a file that has been marked as public. This endpoint requires NO authentication. + + **Access Requirements:** + - The file must have `is_public: true` set via the visibility endpoint + - Private files will return 403 Forbidden + + **Use Cases:** + - Shareable public URLs for profile pictures, public documents, etc. + - Embedding public files on external websites + - Direct linking without requiring SDK or authentication + + **URL Format:** + ``` + GET /public/{projectId}/{bucketName}/{path} + ``` + + **Example:** + ``` + https://api.volcano.dev/public/abc123/avatars/user-photo.jpg + ``` + + **CORS:** + This endpoint allows all origins since the file is already public. + operationId: downloadPublicFile + parameters: + - name: projectId + in: path + required: true + description: Project ID + schema: + type: string + format: uuid + - $ref: '#/components/parameters/BucketName' + - name: path + in: path + required: true + description: Object path within bucket + schema: + type: string + responses: + '200': + description: File content + content: + '*/*': + schema: + type: string + format: binary + '206': + description: Partial content (range request) + '404': + description: Not found (file doesn't exist or is not public) + '429': + $ref: '#/components/responses/BandwidthCapExceeded' + /health: + get: + tags: + - System + summary: Health check endpoint + description: Returns server health status. Used for load balancer and monitoring checks. + operationId: healthCheck + responses: + '200': + description: Server is healthy + content: + text/plain: + schema: + type: string + example: OK + /openapi.json: + get: + tags: + - System + summary: Fetch the OpenAPI specification as JSON + description: | + Returns this specification as a self-contained JSON document, with every + reference resolved. It is generated from the same document the server + validates requests against, so a client generated from it cannot + describe a different API than the one that answers. + + No credential is required: a client generator fetches this by URL before + its user has a token, and every path here is already published in the + API reference. + + The response carries a strong `ETag`; send it back as `If-None-Match` to + get `304 Not Modified` instead of the whole document. + operationId: getOpenAPISpecJSON + security: [] + parameters: + - $ref: '#/components/parameters/IfNoneMatch' + responses: + '200': + description: The OpenAPI specification + headers: + ETag: + $ref: '#/components/headers/ETag' + content: + application/json: + schema: + $ref: '#/components/schemas/OpenAPISpecDocument' + '304': + $ref: '#/components/responses/OpenAPISpecNotModified' + '429': + $ref: '#/components/responses/OpenAPISpecThrottled' + head: + tags: + - System + summary: Check the JSON OpenAPI specification + description: | + The headers `GET /openapi.json` would return, so a cache can pick up the + current `ETag` without transferring the document. + operationId: headOpenAPISpecJSON + security: [] + parameters: + - $ref: '#/components/parameters/IfNoneMatch' + responses: + '200': + $ref: '#/components/responses/OpenAPISpecHeaders' + '304': + $ref: '#/components/responses/OpenAPISpecNotModified' + '429': + $ref: '#/components/responses/OpenAPISpecThrottled' + /openapi.yaml: + get: + tags: + - System + summary: Fetch the OpenAPI specification as YAML + description: | + The same document as `/openapi.json`, serialized as YAML for tools that + prefer it. See that operation for caching and authentication notes. + operationId: getOpenAPISpecYAML + security: [] + parameters: + - $ref: '#/components/parameters/IfNoneMatch' + responses: + '200': + description: The OpenAPI specification + headers: + ETag: + $ref: '#/components/headers/ETag' + content: + application/yaml: + schema: + $ref: '#/components/schemas/OpenAPISpecDocument' + '304': + $ref: '#/components/responses/OpenAPISpecNotModified' + '429': + $ref: '#/components/responses/OpenAPISpecThrottled' + head: + tags: + - System + summary: Check the YAML OpenAPI specification + description: | + The headers `GET /openapi.yaml` would return, so a cache can pick up the + current `ETag` without transferring the document. + operationId: headOpenAPISpecYAML + security: [] + parameters: + - $ref: '#/components/parameters/IfNoneMatch' + responses: + '200': + $ref: '#/components/responses/OpenAPISpecHeaders' + '304': + $ref: '#/components/responses/OpenAPISpecNotModified' + '429': + $ref: '#/components/responses/OpenAPISpecThrottled' + /mcp: + post: + tags: + - System + summary: Model Context Protocol endpoint + description: | + Streamable-HTTP MCP endpoint: one JSON-RPC 2.0 object per request, one + response per request. There is no server-to-client stream, so a `GET` + returns `405`, and a batched array is rejected. + + Authenticated with a **project access token**. The endpoint takes its + project from the credential, so a platform token is refused with `403` — + it names no project, and letting a tool argument choose one would hand an + agent its own blast radius. + + Scope carries over from the REST API. A `read_only` token is not offered + mutating tools or credential-returning reads, and is refused if it calls + one anyway. Revoking the token ends MCP access on the same path it ends + API access. + + Methods: `initialize`, `notifications/initialized`, `ping`, + `tools/list`, `tools/call`. See the + [MCP guide](https://docs.volcano.dev/platform/interfaces/mcp) for the + tool surface and client configuration. + operationId: callMCP + security: + - ProjectAccessToken: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + description: A JSON-RPC 2.0 request object. + required: + - jsonrpc + - method + properties: + jsonrpc: + type: string + enum: + - '2.0' + method: + type: string + description: The MCP method to call. + id: + description: | + Request identifier, echoed verbatim. Omit it to send a + notification, which is answered with `202` and no body. + oneOf: + - type: string + - type: integer + params: + type: object + additionalProperties: true + responses: + '200': + description: A JSON-RPC response object + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + jsonrpc: + type: string + enum: + - '2.0' + id: + description: Echoes the request's id. Null when the request could not be read well enough to determine one. + nullable: true + oneOf: + - type: string + - type: integer + result: + type: object + additionalProperties: true + error: + type: object + required: + - code + - message + properties: + code: + type: integer + message: + type: string + '202': + description: A notification was accepted; there is no body + '401': + description: Not authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: | + The credential is valid but may not use this endpoint — most often a + platform token, which names no project. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '413': + description: The JSON-RPC frame exceeds the 1 MiB limit +components: + headers: + ETag: + description: | + Strong validator for the returned document. Send it back as `If-None-Match` + to revalidate without transferring the document again. + required: true + schema: + type: string + example: '"9f2c1e0b5a"' + DatabaseQueryProxyMs: + description: | + Milliseconds Volcano spent before running the query, counted from the + request arriving: authenticating the caller, validating the request, + resolving the database, and building the SQL. Does not include query + execution. Also present when the query itself failed. + schema: + type: integer + minimum: 0 + DatabaseQueryProxyHandlerMs: + description: | + The part of `X-Volcano-Proxy-Ms` spent in the query endpoint itself. + Subtract it from `X-Volcano-Proxy-Ms` to see what authentication and + request validation cost. Also present when the query itself failed. + schema: + type: integer + minimum: 0 + DatabaseQueryComputeMs: + description: | + Milliseconds the database took to run the query and return its rows. + Does not include Volcano's preparation. Also present when the query + itself failed. + schema: + type: integer + minimum: 0 + securitySchemes: + AnonKey: + type: http + scheme: bearer + bearerFormat: JWT + description: | + Project-specific public key for frontend authentication. + Required for signup, signin, refresh, and logout endpoints. + Get from Project Settings → Authentication → Anon Keys. + Safe to expose in frontend code (scoped to project, limited permissions). + AuthUserAccessToken: + type: http + scheme: bearer + bearerFormat: JWT + description: | + Auth user access token obtained from signup/signin. + Used for authenticated function invocation and user profile access. + Functions invoked with access tokens receive user context in event.__volcano_auth. + Expires after configured lifetime (default: 1 hour). + ServiceRoleKey: + type: http + scheme: bearer + bearerFormat: JWT + description: | + Service role key for admin operations. + **WARNING:** Bypasses Row-Level Security - backend use only! + Create via POST /projects/{id}/service-keys. + Used for function invocation with full database access. + UserToken: + type: http + scheme: bearer + bearerFormat: opaque + description: | + Platform token, which acts on every project in your account. + Obtain one by running `volcano login`, or from the dashboard. + + For CI, scripts, and agents, prefer a project access token + (`pt-`) instead: it reaches only the project it was created in, + so a leak does not expose the rest of your account. See the + ProjectAccessToken scheme. + ProjectAccessToken: + type: http + scheme: bearer + bearerFormat: opaque + description: | + Project access token, scoped to a single project. Starts with `pt-`. + + Accepted on that project's control-plane routes and refused + everywhere else, including account-wide endpoints and any other + project. A `read_only` token additionally refuses mutations. + + Create one with POST /projects/{id}/access-tokens using a platform + token. The secret is returned once and is not recoverable, so a + project access token cannot create, list, read, or revoke project + access tokens. + parameters: + BackupName: + name: backupName + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + description: | + Backup name, unique within the database, exactly as returned by the list + endpoint. + + Deliberately looser than the names you can create: a backup made by a + schedule is named for you, so reading or deleting one accepts any name a + backup can have. + BranchName: + name: branchName + in: path + required: true + schema: + type: string + pattern: ^[a-z0-9_]+$ + maxLength: 64 + description: Branch name (unique within the parent database, lowercase letters, numbers, and underscores only) + BucketName: + name: bucketName + in: path + required: true + schema: + type: string + pattern: ^[a-zA-Z0-9_-]+$ + minLength: 1 + maxLength: 64 + description: Storage bucket name + Cursor: + name: cursor + in: query + required: false + schema: + type: string + description: | + Opaque keyset pagination cursor from a previous response's `next_cursor` + — pages forward. Mutually exclusive with `page` and `ending_before`; + combining them returns 400. When supplied, the request's `search` and + `limit` must match the values bound to the cursor or the request returns 400. + EndingBefore: + name: ending_before + in: query + required: false + schema: + type: string + description: | + Opaque keyset pagination cursor from a previous response's `prev_cursor` + — pages backward (the page immediately preceding this cursor). Mutually + exclusive with `page` and `cursor`; combining them returns 400. `search` + and `limit` must match the values bound to the cursor or the request + returns 400. + DatabaseName: + name: databaseName + in: path + required: true + schema: + type: string + pattern: ^[a-z0-9_]+$ + maxLength: 64 + description: Database name (unique within project, lowercase letters, numbers, and underscores only) + DeploymentId: + name: deploymentId + in: path + required: true + schema: + type: string + format: uuid + description: Frontend deployment ID + FrontendId: + name: frontendId + in: path + required: true + schema: + type: string + format: uuid + description: Frontend ID + FrontendFunctionRouteId: + name: routeId + in: path + required: true + schema: + type: string + format: uuid + description: Frontend Function route ID + FunctionId: + name: functionId + in: path + required: true + schema: + type: string + format: uuid + description: Function ID + DurableFunctionId: + name: functionId + in: path + required: true + schema: + type: string + description: Durable function ID, or its name within the project + DurableExecutionId: + name: executionId + in: path + required: true + schema: + type: string + format: uuid + description: Durable execution ID + Limit: + name: limit + in: query + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 10 + description: Number of items per page (max 100) + LockKey: + name: key + in: path + required: true + description: Project-local lock name. + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$ + LockToken: + name: X-Volcano-Lock-Token + in: header + required: true + description: Opaque UUID generated once by the caller and retained for the lease lifetime. + schema: + type: string + format: uuid + LockRequestId: + name: X-Volcano-Request-Id + in: header + required: true + description: | + UUID correlating this request across client and server logs. Repeat safety comes from + the lock token, so a retry under a reused request ID still counts against the quota. + schema: + type: string + format: uuid + DeploymentOperation: + name: operation + in: query + required: false + description: Restrict a deployment feed to one kind of operation. + schema: + type: string + enum: + - deploy + - redeploy + - update + - delete + DeploymentOwnerId: + name: owner_id + in: query + required: false + description: | + The user who owns the projects whose deployments to return + (`projects.user_id`). This is ownership, not the actor that started the + deployment — see `initiated_by_user_id` for that. Not a UUID: platform + user ids are opaque strings. + schema: + type: string + maxLength: 255 + DeploymentOrder: + name: order + in: query + required: false + description: | + Sort key and direction. `created_at.desc` (default) is the feed order. + `completed_at.asc` orders finished attempts by completion, oldest first, + and excludes attempts that never completed. + schema: + type: string + enum: + - created_at.desc + - completed_at.asc + default: created_at.desc + DeploymentResourceType: + name: resource_type + in: query + required: false + description: | + Restrict a deployment feed to a single resource type. Omit to return + both Function and Frontend deployments. + schema: + type: string + enum: + - function + - frontend + DeploymentStatus: + name: status + in: query + required: false + description: Restrict a deployment feed to attempts in one status. + schema: + type: string + enum: + - queued + - provisioning + - active + - degraded + - failed + - superseded + - deleting + - deleted + Offset: + name: offset + in: query + required: false + schema: + type: integer + minimum: 0 + default: 0 + description: | + Bounded row offset past the keyset anchor named by `cursor` (forward) or + `ending_before` (backward) — the hybrid jump. Seek to the anchor, then + skip this many rows within. Used for numbered jump-to-page: from the + current page, seek to its next/prev cursor and offset the remaining + pages. Only honored on the cursor pagination path; ignored otherwise. + Page: + name: page + in: query + required: false + schema: + type: integer + minimum: 1 + description: | + Page number (1-indexed) for offset pagination. Declares no schema + default so the request validator does not inject one: handlers that omit + `page` see it unset (nil) and default to 1 in code, while cursor-first + endpoints (e.g. the project deployments feed) can detect its absence to + stay in keyset/search mode. Supplying `page` selects offset pagination. + ProjectId: + name: id + in: path + required: true + schema: + type: string + format: uuid + description: Project ID + TokenId: + name: tokenId + in: path + required: true + schema: + type: string + format: uuid + description: Project access token ID + Search: + name: search + in: query + required: false + schema: + type: string + maxLength: 256 + description: | + Case-insensitive substring match on the resource `name`. See the + endpoint description for supported pagination modes. + RestoreId: + name: restoreId + in: path + required: true + schema: + type: string + format: uuid + description: Database restore ID + SchedulerId: + name: schedulerId + in: path + required: true + schema: + type: string + format: uuid + description: Function scheduler ID + VariableName: + name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 256 + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + description: Variable name. Function runtime names such as AWS_REGION are reserved and cannot be updated. + IfNoneMatch: + name: If-None-Match + in: header + required: false + description: | + Entity tag from an earlier response, returning `304 Not Modified` while it + still matches. Accepts the full condition: `*`, a comma-separated list, and + weak tags of the form `W/"tag"`. + schema: + type: string + example: '"9f2c1e0b5a"' + responses: + OpenAPISpecThrottled: + description: | + Too many requests for the specification from one address. The document + carries an `ETag`; revalidate with `If-None-Match` rather than + re-fetching it. + headers: + Retry-After: + description: Seconds to wait before requesting the specification again. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + BandwidthCapExceeded: + description: | + The platform user exceeded their billing-cycle bandwidth allowance (aggregate + ingress + egress across owned projects). Enforcement is eventual: + requests are rejected until the allowance increases or the next + anniversary cycle begins. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + DatabaseQueryCapExceeded: + description: | + The query was rejected by a billing-cycle allowance: either the owning + platform user's bandwidth allowance (aggregate ingress + egress across + owned projects) or their database-request allowance. Enforcement is + eventual: queries are rejected until the allowance increases or the + next anniversary cycle begins. The error message identifies the resource. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + DatabaseBranchQueryUnavailable: + description: | + The branch exists but cannot serve queries: it is still provisioning, + being reset, expired, or its parent is being restored. Distinct from + `404` so a caller waiting on a branch can tell it apart from a typo. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + OpenAPISpecNotModified: + description: | + The specification still matches the supplied `If-None-Match`, so no body + is returned. + headers: + ETag: + $ref: '#/components/headers/ETag' + OpenAPISpecHeaders: + description: | + The headers a `GET` would return, without the document. The declared + `ETag` is the one to revalidate against. + headers: + ETag: + $ref: '#/components/headers/ETag' + schemas: + SandboxPreset: + type: object + additionalProperties: false + properties: + id: + type: string + runtime: + type: string + version: + type: string + memory_mb: + type: integer + enum: + - 1024 + - 2048 + regions: + type: array + items: + type: string + required: + - id + - runtime + - version + - memory_mb + - regions + SandboxTemplate: + type: object + additionalProperties: false + properties: + id: + type: string + format: uuid + project_id: + type: string + format: uuid + name: + type: string + pattern: ^[a-z][a-z0-9-]{0,62}$ + preset: + type: string + memory_mb: + type: integer + status: + type: string + enum: + - ready + - unavailable + - deleting + created_at: + type: string + format: date-time + required: + - id + - project_id + - name + - status + - created_at + CreateSandboxTemplateRequest: + type: object + additionalProperties: false + properties: + name: + type: string + pattern: ^[a-z][a-z0-9-]{0,62}$ + preset: + type: string + enum: + - python3.12 + - node22 + memory_mb: + type: integer + enum: + - 1024 + - 2048 + default: 1024 + required: + - name + - preset + UpdateSandboxTemplateRequest: + type: object + additionalProperties: false + properties: + name: + type: string + pattern: ^[a-z][a-z0-9-]{0,62}$ + required: + - name + SandboxSession: + type: object + additionalProperties: false + properties: + id: + type: string + format: uuid + project_id: + type: string + format: uuid + sandbox_id: + type: string + format: uuid + state: + type: string + enum: + - starting + - running + - suspending + - suspended + - resuming + - terminating + - terminated + - unknown + desired_state: + type: string + enum: + - running + - suspended + - terminated + region: + type: string + memory_mb: + type: integer + created_at: + type: string + format: date-time + started_at: + type: string + format: date-time + expires_at: + type: string + format: date-time + required: + - id + - project_id + - sandbox_id + - state + - desired_state + - region + - memory_mb + - created_at + - expires_at + CreateSandboxSessionRequest: + type: object + additionalProperties: false + properties: + preset: + type: string + enum: + - python3.12 + - node22 + sandbox_id: + type: string + format: uuid + memory_mb: + type: integer + enum: + - 1024 + - 2048 + region: + type: string + pattern: ^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$ + description: Region such as `us-east-1`. Region IDs issued by earlier versions of the API are still accepted. + max_duration_seconds: + type: integer + minimum: 30 + maximum: 28800 + default: 3600 + idle_timeout_seconds: + type: integer + minimum: 0 + maximum: 28800 + default: 0 + required: + - region + oneOf: + - required: + - preset + not: + required: + - sandbox_id + - required: + - sandbox_id + not: + required: + - preset + SandboxCommandRequest: + type: object + additionalProperties: false + properties: + command: + type: string + minLength: 1 + maxLength: 65536 + timeout_seconds: + type: integer + minimum: 1 + maximum: 3600 + default: 60 + environment: + type: object + additionalProperties: + type: string + maxProperties: 64 + required: + - command + SandboxExecutionRequest: + type: object + additionalProperties: false + properties: + preset: + type: string + enum: + - python3.12 + - node22 + sandbox_id: + type: string + format: uuid + memory_mb: + type: integer + enum: + - 1024 + - 2048 + region: + type: string + pattern: ^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$ + description: Region such as `us-east-1`. Region IDs issued by earlier versions of the API are still accepted. + command: + type: string + minLength: 1 + maxLength: 65536 + timeout_seconds: + type: integer + minimum: 1 + maximum: 60 + default: 60 + environment: + type: object + additionalProperties: + type: string + maxProperties: 64 + required: + - region + - command + oneOf: + - required: + - preset + not: + required: + - sandbox_id + - required: + - sandbox_id + not: + required: + - preset + SandboxCommandResult: + type: object + additionalProperties: false + properties: + stdout: + type: string + stderr: + type: string + exit_code: + type: integer + stdout_truncated: + type: boolean + stderr_truncated: + type: boolean + timed_out: + type: boolean + required: + - stdout + - stderr + - exit_code + - stdout_truncated + - stderr_truncated + - timed_out + SandboxExecutionResult: + type: object + additionalProperties: false + properties: + stdout: + type: string + stderr: + type: string + exit_code: + type: integer + stdout_truncated: + type: boolean + stderr_truncated: + type: boolean + timed_out: + type: boolean + session_id: + type: string + format: uuid + region: + type: string + duration_ms: + type: integer + format: int64 + minimum: 0 + required: + - stdout + - stderr + - exit_code + - stdout_truncated + - stderr_truncated + - timed_out + - session_id + - region + - duration_ms + SandboxFileWriteRequest: + type: object + additionalProperties: false + properties: + path: + type: string + minLength: 1 + maxLength: 4096 + data: + type: string + format: byte + maxLength: 11184812 + required: + - path + - data + SandboxFileReadRequest: + type: object + additionalProperties: false + properties: + path: + type: string + minLength: 1 + maxLength: 4096 + required: + - path + SandboxFileResult: + type: object + additionalProperties: false + properties: + data: + type: string + format: byte + required: + - data + SandboxSubjectGrantRequest: + type: object + additionalProperties: false + properties: + expires_at: + type: string + format: date-time + required: + - expires_at + SandboxAccessRequest: + type: object + additionalProperties: false + properties: + port: + type: integer + minimum: 1 + maximum: 65532 + expires_in_seconds: + type: integer + minimum: 1 + maximum: 300 + default: 300 + required: + - port + SandboxAccess: + type: object + additionalProperties: false + properties: + url: + type: string + format: uri + token: + type: string + expires_at: + type: string + format: date-time + required: + - url + - token + - expires_at + SandboxDeployment: + type: object + additionalProperties: false + properties: + id: + type: string + format: uuid + status: + type: string + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + required: + - id + - status + - created_at + - updated_at + SandboxPagination: + type: object + additionalProperties: false + properties: + limit: + type: integer + has_more: + type: boolean + next_cursor: + type: string + required: + - limit + - has_more + SandboxTemplatePage: + type: object + additionalProperties: false + properties: + data: + type: array + items: + $ref: '#/components/schemas/SandboxTemplate' + pagination: + $ref: '#/components/schemas/SandboxPagination' + required: + - data + - pagination + SandboxSessionPage: + type: object + additionalProperties: false + properties: + data: + type: array + items: + $ref: '#/components/schemas/SandboxSession' + pagination: + $ref: '#/components/schemas/SandboxPagination' + required: + - data + - pagination + SandboxDeploymentPage: + type: object + additionalProperties: false + properties: + data: + type: array + items: + $ref: '#/components/schemas/SandboxDeployment' + pagination: + $ref: '#/components/schemas/SandboxPagination' + required: + - data + - pagination + SandboxPresetList: + type: object + additionalProperties: false + properties: + data: + type: array + items: + $ref: '#/components/schemas/SandboxPreset' + required: + - data + SandboxCapacity: + type: object + additionalProperties: false + properties: + region: + type: string + allocated_memory_mb: + type: integer + format: int64 + minimum: 0 + required: + - region + - allocated_memory_mb + SandboxCapacityList: + type: object + additionalProperties: false + properties: + data: + type: array + items: + $ref: '#/components/schemas/SandboxCapacity' + required: + - data + PublishSandboxPresetRequest: + type: object + additionalProperties: false + properties: + id: + type: string + format: uuid + preset: + type: string + enum: + - python3.12 + - node22 + memory_mb: + type: integer + enum: + - 1024 + - 2048 + deployment_id: + type: string + format: uuid + required: + - id + - preset + - memory_mb + - deployment_id AnonKey: type: object properties: @@ -12735,7 +15233,7 @@ components: type: integer format: int64 minimum: 0 - description: Accounts created during the bucket. + description: Accounts created during the bucket that still exist. signins: type: integer format: int64 @@ -13355,11 +15853,12 @@ components: region: type: string description: | - Region for database hosting. The accepted values are the regions this - environment runs in, so read them from `GET /databases/regions` rather - than hardcoding a list. A region the environment does not offer is - rejected with 400. - example: aws-us-east-1 + Region for database hosting, such as `us-east-1`. The accepted values + are the regions this environment runs in, so read them from + `GET /databases/regions` rather than hardcoding a list. A region the + environment does not offer is rejected with 400. Region IDs issued by + earlier versions of the API are still accepted. + example: us-east-1 pg_version: type: string description: PostgreSQL major version @@ -13619,6 +16118,7 @@ components: description: Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable. name: type: string + description: Project variable name. Function runtime names such as AWS_REGION are reserved and return 400; see the environment variables guide for the full list. minLength: 1 maxLength: 256 pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ @@ -13674,7 +16174,7 @@ components: region: type: string description: Region where the database is hosted - example: aws-us-east-1 + example: us-east-1 pg_version: type: string description: PostgreSQL major version @@ -15146,6 +17646,20 @@ components: Frontend: type: object properties: + variable_scope: + type: string + enum: + - all + - shared + - scoped + description: All preserves access to all project variables. Shared includes the project frontend shared-variable list. Scoped includes only explicitly declared variables in builds and runtime. Omission preserves the stored selection. + declared_variables: + type: array + uniqueItems: true + items: + type: string + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + description: Names selected when variable_scope is scoped. Missing declared values reject deployment. Omission preserves the stored list; an empty list clears it. id: type: string format: uuid @@ -15229,6 +17743,72 @@ components: - deployed_regions - created_at - updated_at + FrontendFunctionRoute: + type: object + additionalProperties: false + properties: + id: + type: string + format: uuid + project_id: + type: string + format: uuid + frontend_id: + type: string + format: uuid + function_id: + type: string + format: uuid + path_prefix: + type: string + minLength: 2 + maxLength: 512 + pattern: ^/[^?#\\]*[^/?#\\]$ + strip_prefix: + type: boolean + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + required: + - id + - project_id + - frontend_id + - function_id + - path_prefix + - strip_prefix + - created_at + - updated_at + FrontendFunctionRouteList: + type: object + additionalProperties: false + properties: + data: + type: array + items: + $ref: '#/components/schemas/FrontendFunctionRoute' + required: + - data + CreateFrontendFunctionRouteRequest: + type: object + additionalProperties: false + properties: + function_id: + type: string + format: uuid + path_prefix: + type: string + minLength: 2 + maxLength: 512 + pattern: ^/[^?#\\]*[^/?#\\]$ + strip_prefix: + type: boolean + default: false + required: + - function_id + - path_prefix FrontendCustomDomainResponse: type: object properties: @@ -15259,6 +17839,9 @@ components: $ref: '#/components/schemas/FrontendDomainVerificationRecord' required_routing_record: $ref: '#/components/schemas/FrontendDomainRoutingRecord' + routing_target_hostname: + type: string + description: DNS routing target hostname for this frontend. The DNS record type depends on whether the custom domain is a zone apex. effective_urls: type: array items: @@ -15345,28 +17928,19 @@ components: initiated_by: type: string description: Platform user that triggered a request-initiated deployment; absent for git and system deployments. - artifact_bucket: - type: string - artifact_key: - type: string - artifact_version: - type: string site_url: type: string - cloudformation_stack_id: - type: string - cloudformation_stack_url: - type: string - codebuild_duration_seconds: + build_duration_seconds: type: integer format: int64 - description: Total CodeBuild build duration recorded for this deployment, in seconds. - codebuild_build_count: + description: Total build time recorded for this deployment, in seconds. + build_count: type: integer - description: Number of completed CodeBuild builds included in codebuild_duration_seconds. - codebuild_duration_recorded_at: + description: Number of completed builds included in build_duration_seconds. + build_duration_recorded_at: type: string format: date-time + description: When the build time was last recorded. progress: $ref: '#/components/schemas/DeploymentProgress' error_message: @@ -15398,96 +17972,307 @@ components: value: type: string required: - - record_type + - record_type + - name + - value + FrontendDomainVerificationRecord: + type: object + properties: + name: + type: string + type: + type: string + value: + type: string + required: + - name + - type + - value + FrontendUsageDailyEntry: + type: object + description: One day of request and error counts for a single frontend. + properties: + day: + type: string + format: date + description: UTC date (YYYY-MM-DD) the counts cover. + requests: + type: integer + format: int64 + description: Total requests served on this day. + errors: + type: integer + format: int64 + description: 5xx responses served on this day. + page_views: + type: integer + format: int64 + description: Navigable-document responses served on this day (text/html or Sec-Fetch-Dest=document) — strict subset of `requests`. + required: + - day + - requests + - errors + - page_views + FrontendUsageData: + type: object + description: Monthly frontend request totals grouped by frontend. + properties: + frontend_id: + type: string + format: uuid + description: Frontend ID + frontend_name: + type: string + description: Frontend name at the time usage was fetched + nullable: true + requests: + type: integer + format: int64 + description: Total requests for this frontend in the current usage month + required: + - frontend_id + - requests + FrontendUsageHistoryResponse: + type: object + description: Zero-filled daily series of request + error counts for a single frontend, oldest first. + properties: + frontend_id: + type: string + format: uuid + days: + type: integer + description: Number of daily entries returned (always equal to the `days` query param after clamping). + daily: + type: array + items: + $ref: '#/components/schemas/FrontendUsageDailyEntry' + total_requests: + type: integer + format: int64 + total_errors: + type: integer + format: int64 + total_page_views: + type: integer + format: int64 + required: + - frontend_id + - days + - daily + - total_requests + - total_errors + - total_page_views + ProjectAccessToken: + type: object + description: | + A project access token: a control-plane credential bound to a single + project. Unlike a platform token, which acts on every project its owner + has, this one is limited to the project it was created in. + + The secret itself is never returned here. Only its hash is stored, so + the plaintext exists solely in the response to the create call. + properties: + id: + type: string + format: uuid + project_id: + type: string + format: uuid + name: + type: string + description: Unique per project. + token_prefix: + type: string + description: First 12 characters of the secret, for recognising a token in a list. + scope: + $ref: '#/components/schemas/ProjectAccessTokenScope' + status: + type: string + enum: + - active + - revoked + - expired + description: | + `revoked` means the token was deliberately revoked, by you or by the + deletion of its project. `expired` means it simply reached + `expires_at`; nothing was taken away. Both are refused, and both keep + their record so a token's name, prefix, last use, and request history + remain available after a leak. + + A token revoked before its expiry passed stays `revoked`, because + that is the fact worth keeping. + token_source: + type: string + enum: + - api + - cli + - dashboard + description: What created the token. + expires_at: + type: string + format: date-time + nullable: true + description: Absent for a token that does not expire. + last_used_at: + type: string + format: date-time + nullable: true + description: Updated at most once every few minutes, so it may lag slightly. + created_at: + type: string + format: date-time + all_time_requests: + type: integer + format: int64 + description: Requests authenticated with this token since it was created. + required: + - id + - project_id - name - - value - FrontendDomainVerificationRecord: + - token_prefix + - scope + - status + - token_source + - created_at + - all_time_requests + ProjectAccessTokenScope: + type: string + description: | + What a project access token may do within its project. + + `full` is everything you can do to that one project, up to and including + deleting it. It cannot manage access tokens, so a leaked token cannot + mint a replacement or erase the record of its own use, but for a CI or + agent credential that only deploys, prefer `read_only` where the job + allows it. + + `read_only` refuses mutations. It is enforced by route classification + rather than HTTP method, so the log and metrics query endpoints remain + available even though they are POST requests that carry body filters. + + `read_only` also refuses the reads that return a credential — service + keys, anon keys, variable values, and database connection strings. Those + grant write access over the project's data and keep working after the + token that fetched them is revoked, so returning one to a read-only + credential would make the scope a formality. An anon key is included + because its permissions are chosen per key and may include uploading, + deleting, and publishing. + enum: + - full + - read_only + x-enum-varnames: + - ProjectAccessTokenScopeFull + - ProjectAccessTokenScopeReadOnly + CreateProjectAccessTokenRequest: type: object properties: name: type: string - type: - type: string - value: + minLength: 1 + maxLength: 100 + description: | + Held by any of the project's tokens you have not revoked, including + one that has expired. Creating a duplicate returns 409 with code + `access_token_name_exists`; revoking the holder frees the name, so a + rotation can keep the name its caller already references. + scope: + $ref: '#/components/schemas/ProjectAccessTokenScope' + expires_at: type: string + format: date-time + description: Omit for a token that does not expire. required: - name - - type - - value - FrontendUsageDailyEntry: + - scope + CreatedProjectAccessToken: + allOf: + - $ref: '#/components/schemas/ProjectAccessToken' + - type: object + properties: + token: + type: string + description: | + The secret. Returned only here, and not recoverable afterwards: + the server stores a hash rather than the value. Save it now. + required: + - token + PaginatedProjectAccessTokens: type: object - description: One day of request and error counts for a single frontend. properties: - day: - type: string - format: date - description: UTC date (YYYY-MM-DD) the counts cover. - requests: + data: + type: array + items: + $ref: '#/components/schemas/ProjectAccessToken' + page: type: integer - format: int64 - description: Total requests served on this day. - errors: + limit: type: integer - format: int64 - description: 5xx responses served on this day. - page_views: + total: type: integer - format: int64 - description: Navigable-document responses served on this day (text/html or Sec-Fetch-Dest=document) — strict subset of `requests`. + has_more: + type: boolean + next: + type: string required: - - day - - requests - - errors - - page_views - FrontendUsageData: + - data + - page + - limit + - total + - has_more + ProjectAccessTokenUsage: type: object - description: Monthly frontend request totals grouped by frontend. + description: | + Zero-filled daily request counts for a single token, oldest first. Every + day in the window is present, so a gap reads as zero rather than missing. + + Counts every request the token authenticated, including ones then + refused — a read-only token attempting a write, or a token presented on + another project's route. That is deliberate: after a leak, the probing + is the part you want to see, and a counter that hid it would make a + token look idle while it was being tried. properties: - frontend_id: + token_id: type: string format: uuid - description: Frontend ID - frontend_name: + name: type: string - description: Frontend name at the time usage was fetched - nullable: true - requests: - type: integer - format: int64 - description: Total requests for this frontend in the current usage month - required: - - frontend_id - - requests - FrontendUsageHistoryResponse: - type: object - description: Zero-filled daily series of request + error counts for a single frontend, oldest first. - properties: - frontend_id: + token_prefix: type: string - format: uuid + description: | + The token's display prefix, which identifies the credential when its + name does not. Revoking frees a name, so a project that rotated + `ci-deploy` has two entries here both called `ci-deploy`. Not usable + as a credential. days: type: integer - description: Number of daily entries returned (always equal to the `days` query param after clamping). + description: Number of daily entries returned, always equal to the requested window. daily: type: array items: - $ref: '#/components/schemas/FrontendUsageDailyEntry' + $ref: '#/components/schemas/ProjectAccessTokenUsageDailyEntry' total_requests: type: integer format: int64 - total_errors: - type: integer - format: int64 - total_page_views: - type: integer - format: int64 required: - - frontend_id + - token_id + - name + - token_prefix - days - daily - total_requests - - total_errors - - total_page_views + ProjectAccessTokenUsageDailyEntry: + type: object + properties: + day: + type: string + format: date + description: UTC day. + requests: + type: integer + format: int64 + required: + - day + - requests Function: type: object properties: @@ -15530,11 +18315,9 @@ components: has_openapi_spec: type: boolean description: Whether OpenAPI metadata is configured; list responses omit the document itself. - aws_function_arn: - type: string invoke_url: type: string - description: Canonical GeoDNS endpoint URL for invoking this function (always HTTPS) + description: 'Canonical geo-routed HTTPS endpoint for invoking this function. Use it as-is: it does not share a domain with the API, so a host derived from the API URL will not reach the function. Omitted when the deployment serves no public invocation domain, as in local development, so a client testing for an empty string never matches.' deployed_regions: type: array items: @@ -15761,12 +18544,18 @@ components: `succeeded`, `failed`, `timed_out`, `stopped` and `unknown` are terminal. - `unknown` means the platform lost track of the execution's outcome: it - was never seen to finish and is no longer reported, so no result or - error can be given for it. It is terminal because nothing can settle it - later, and it is rare — treat it as an outcome to retry under a new - name rather than a state to wait on. `completed_at` on an `unknown` - execution is when the platform gave up, not when the work ended. + `unknown` means the execution's outcome cannot be established, so no + result or error can be given for it. Either it was under way and was + never seen to finish, or its start failed with a `500` without the + platform establishing whether the execution began — which is why a + name whose start returned an error can later read as `unknown` rather + than not being found. It is terminal because nothing can settle it + later, and it is rare — treat it as an outcome to retry rather than a + state to wait on. A retry under the same name picks this execution back + up instead of starting a second one, and needs a free concurrency slot + because an `unknown` execution has given its own up. `completed_at` on + an `unknown` execution is when the platform gave up, not when the work + ended. DurableExecutionError: type: object description: Why a failed or timed-out execution ended. @@ -15775,6 +18564,187 @@ components: type: string message: type: string + DurableExecutionOperationList: + type: object + description: A durable execution's trace. + properties: + data: + type: array + description: | + Every operation the execution began. The execution itself comes + first and is the only operation without a `parent_id`; the rest + follow in the order they started. + items: + $ref: '#/components/schemas/DurableExecutionOperation' + invocations: + type: array + description: | + When the function's code was running, oldest first. An execution + suspended in a wait holds no runtime, so the gaps between these are + not charged as compute. + items: + $ref: '#/components/schemas/DurableExecutionInvocation' + complete: + type: boolean + description: | + `true` once the execution has finished and nothing more will be + recorded. Its operations no longer change, and it is no longer + refreshed on read; a final invocation window can still be added + shortly after. + synced_at: + type: string + format: date-time + description: | + When the trace was last refreshed. Absent before it has been + refreshed at all. A running execution's trace is usually within + about ten seconds of the execution, and further behind when many + executions are being watched at once. + required: + - data + - invocations + - complete + DurableExecutionOperation: + type: object + description: One operation on an execution's timeline. + properties: + id: + type: string + description: Identifies the operation within its execution. + parent_id: + type: string + description: | + The operation this one ran inside: a child context, map item or + parallel branch, or the execution itself for top-level work. Absent + only on the execution. + name: + type: string + description: | + The name the handler gave the operation. Map items and parallel + branches the handler did not name carry the SDK's positional name, + such as `map-item-0`. Absent for an unnamed operation. + type: + type: string + enum: + - execution + - step + - wait + - callback + - context + - chained_invoke + description: The kind of checkpointed operation Volcano recorded. + kind: + type: string + enum: + - execution + - step + - wait + - wait_until + - callback + - child + - map + - map_item + - parallel + - parallel_branch + - invoke + description: | + The operation as the handler wrote it: `ctx.step` is `step`, + `ctx.wait` is `wait`, `ctx.waitUntil` is `wait_until`, `ctx.child` + is `child`, `ctx.map` is `map` with one `map_item` per item, and + `ctx.parallel` is `parallel` with one `parallel_branch` per branch. + status: + type: string + enum: + - running + - waiting + - retrying + - succeeded + - failed + - cancelled + - timed_out + - stopped + - unknown + description: | + Where the operation stands. `waiting` holds no runtime: a wait that + has not elapsed, or a `waitUntil` between checks. `retrying` is a step whose last attempt failed and + whose next one is scheduled at `next_attempt_at`. Work still open + when the execution ended is `cancelled` at the moment it ended. + `unknown` is only ever the execution itself, when its outcome was + lost with its history, as in the execution's own `unknown` status. + started_at: + type: string + format: date-time + ended_at: + type: string + format: date-time + description: Present once the operation has ended. + scheduled_end_at: + type: string + format: date-time + description: When a wait is due to elapse. + next_attempt_at: + type: string + format: date-time + description: | + When a step's next attempt, or a `waitUntil`'s next check, is due. + Present only while one is scheduled. + attempts: + type: array + description: | + Each run of a step's body, in order. Present on steps and + `waitUntil` polls, where each check is an attempt. + items: + $ref: '#/components/schemas/DurableExecutionOperationAttempt' + error: + $ref: '#/components/schemas/DurableExecutionError' + required: + - id + - type + - kind + - status + - started_at + DurableExecutionOperationAttempt: + type: object + description: One run of a step's body. + properties: + attempt: + type: integer + minimum: 1 + description: The attempt's number, starting at 1. + status: + type: string + enum: + - running + - succeeded + - failed + description: | + How the attempt ended. A `waitUntil` check whose condition did not + hold yet is `succeeded`: the check ran, and the poll continues. + started_at: + type: string + format: date-time + ended_at: + type: string + format: date-time + description: Present once the attempt has ended. + error: + $ref: '#/components/schemas/DurableExecutionError' + required: + - attempt + - status + - started_at + DurableExecutionInvocation: + type: object + description: A window in which the function's code was running. + properties: + started_at: + type: string + format: date-time + ended_at: + type: string + format: date-time + required: + - started_at + - ended_at FunctionInvocationMode: type: string enum: @@ -15835,22 +18805,17 @@ components: initiated_by: type: string description: Platform user that triggered a request-initiated deployment; absent for git and system deployments. - artifact_bucket: - type: string - artifact_key: - type: string - artifact_version: - type: string - codebuild_duration_seconds: + build_duration_seconds: type: integer format: int64 - description: Total CodeBuild build duration recorded for this deployment, in seconds. - codebuild_build_count: + description: Total build time recorded for this deployment, in seconds. + build_count: type: integer - description: Number of completed CodeBuild builds included in codebuild_duration_seconds. - codebuild_duration_recorded_at: + description: Number of completed builds included in build_duration_seconds. + build_duration_recorded_at: type: string format: date-time + description: When the build time was last recorded. progress: $ref: '#/components/schemas/DeploymentProgress' error_message: @@ -15900,16 +18865,16 @@ components: additionalProperties: true LogActivityBucket: type: object - description: Log-event counts for one activity time bucket. + description: Log-event counts for one activity time bucket. The first and last buckets can extend past the requested window; they count only events inside it. properties: start_time: type: string format: date-time - description: Bucket start time. + description: Bucket start time, inclusive. end_time: type: string format: date-time - description: Bucket end time. + description: Bucket end time, exclusive. counts: type: object description: Counts grouped by activity dimension. @@ -15955,16 +18920,16 @@ components: start_time: type: string format: date-time - description: Start time. + description: Start of the window, inclusive. Defaults to 24 hours before `end_time`. end_time: type: string format: date-time - description: End time. + description: End of the window, exclusive. Defaults to now. bucket_count: type: integer minimum: 1 maximum: 96 - description: Number of activity buckets to return. + description: Maximum number of buckets. Defaults to 24. Volcano picks the smallest bucket width from 1s, 2s, 5s, 10s, 15s, 30s, 1m, 2m, 5m, 10m, 15m, 30m, 1h, 2h, 3h, 6h, 12h, 1d, or a whole number of days that covers the window in at most this many buckets. Bucket edges fall on UTC multiples of the width, so they stay fixed as the window moves, and the response can contain fewer buckets. `1` returns one bucket that spans exactly the window. required: - resource LogActivityResponse: @@ -16062,10 +19027,10 @@ components: description: Number of items requested per page. has_more: type: boolean - description: Whether there are more log events available. + description: Whether the search may have more matching log events. A page can hold fewer than `limit` events, or none, while this is true; keep paging until it is false. next_cursor: type: string - description: Opaque cursor for the next page. Send this value as `cursor` on the next request. + description: Opaque cursor for the next page, present while `has_more` is true. Send this value as `cursor` on the next request, even when `data` is empty. required: - data - limit @@ -16093,6 +19058,7 @@ components: type: object required: - name + - label - language - default - durable_capable @@ -16102,6 +19068,10 @@ components: type: string example: nodejs24.x description: Runtime identifier accepted by function APIs. + label: + type: string + example: Node.js 24 + description: Human-readable runtime label suitable for display in pickers. language: type: string example: nodejs @@ -16313,7 +19283,7 @@ components: description: | Metric name (for example, "Function & Frontend Invocations", "Frontend Requests", "Durable Executions", "Durable Operations", "Durable Compute (MB-Seconds)", - "CodeBuild Build Seconds", + "Build Seconds", "Bandwidth Ingress (Bytes)", "Bandwidth Egress (Bytes)", "Bandwidth Total (Bytes)", or "Database Storage (Bytes)"). Byte-based metrics are reported in bytes. "Bandwidth Total (Bytes)" is derived (ingress + egress) and @@ -16886,9 +19856,7 @@ components: enum: - HOBBY - SUPERAGENT - - FREE - - PRO - description: Public plan name; FREE and PRO are accepted from older Hosting responses. + description: Plan name applied to the project when available. all_regions: type: boolean description: | @@ -16900,8 +19868,6 @@ components: items: type: string description: Effective region set for this project (normalized and deduplicated) - aws_application_name: - type: string last_invoked_at: type: string format: date-time @@ -16969,6 +19935,14 @@ components: items: type: string pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + frontend_shared_variables: + type: array + uniqueItems: true + description: Replace the complete shared frontend-variable list with existing names. Frontends with variable_scope shared receive this list. Omission keeps membership unchanged; an empty list clears it. + items: + type: string + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + maxLength: 256 variables: type: array description: Fully synced when declared - variables absent from this list are deleted. @@ -17395,7 +20369,7 @@ components: minLength: 1 region: type: string - description: Deployed region ID (e.g. aws-us-east-1). Asserted, never written. + description: Deployed region ID (e.g. us-east-1). Asserted, never written; region IDs issued by earlier versions of the API match too. pg_version: type: string enum: @@ -17457,11 +20431,31 @@ components: created or deleted through the manifest. A declared frontend entry without `custom_domain` deletes an existing custom domain. properties: + variable_scope: + type: string + enum: + - all + - shared + - scoped + description: All preserves access to all project variables. Shared includes the project frontend_shared_variables list. Scoped includes only explicitly declared variables in builds and runtime. Omission preserves the stored selection. + variables: + type: array + uniqueItems: true + items: + type: string + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + description: Names selected when variable_scope is scoped. Missing declared values reject deployment. Omission preserves the stored list; an empty list clears it. name: type: string minLength: 1 custom_domain: $ref: '#/components/schemas/ProjectConfigCustomDomain' + function_routes: + type: array + maxItems: 64 + description: Complete set of same-origin Function path mappings when declared. Omission preserves existing mappings; an empty list deletes all mappings. + items: + $ref: '#/components/schemas/ProjectConfigFrontendFunctionRoute' required: - name ProjectConfigFunction: @@ -17488,6 +20482,9 @@ components: enum: - all - scoped + x-enum-varnames: + - ProjectConfigFunctionVariableScopeAll + - ProjectConfigFunctionVariableScopeScoped description: | Which project variables this function receives. `all` (the default) gives it the project variables marked `shared: true`. `scoped` gives it only the variables @@ -17732,6 +20729,7 @@ components: description: Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable. name: type: string + description: Project variable name. Function runtime names such as AWS_REGION are reserved and fail validation; see the environment variables guide for the full list. minLength: 1 value: type: string @@ -18101,8 +21099,6 @@ components: - system - unknown description: What initiated this deployment. - artifact_version: - type: string error_message: type: string completed_at: @@ -18179,7 +21175,7 @@ components: format: double minimum: 0 nullable: true - description: Median CodeBuild duration across eligible completed attempts. + description: Median build duration across eligible completed attempts. required: - deployment_count - successful_count @@ -18299,6 +21295,9 @@ components: type: string format: uuid description: Canonical function ID used for invocation routing + invoke_url: + type: string + description: 'Canonical HTTPS endpoint for invoking this function. Use it as-is: it does not share a domain with the API, so a host derived from the API URL will not reach the function. Omitted when the deployment serves no public invocation domain, as in local development; invoke through POST /functions/{functionId}/invoke instead.' cache_ttl_seconds: type: integer minimum: 1 @@ -19079,6 +22078,9 @@ components: shared: type: boolean description: Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable. + frontend_shared: + type: boolean + description: Whether this name is in the project's shared frontend-variable list. id: type: string format: uuid @@ -19128,6 +22130,12 @@ components: - value - created_at - updated_at + OpenAPISpecDocument: + type: object + additionalProperties: true + description: | + This OpenAPI document, with every reference resolved. Shared by the JSON + and YAML operations, which differ only in serialization. ProjectGitConnectionSummary: type: object properties: @@ -19221,6 +22229,25 @@ components: $ref: '#/components/schemas/AuthPageTheme' layouts: $ref: '#/components/schemas/ProjectConfigAuthPageLayouts' + ProjectConfigFrontendFunctionRoute: + type: object + additionalProperties: false + properties: + function: + type: string + minLength: 1 + description: Name of an existing standard Function configured for HTTP invocation. + path_prefix: + type: string + minLength: 2 + maxLength: 512 + pattern: ^/[^?#\\]*[^/?#\\]$ + strip_prefix: + type: boolean + default: false + required: + - function + - path_prefix DatabaseQueryPerformanceDatabase: type: object properties: @@ -19241,12 +22268,12 @@ components: query: type: string maxLength: 8192 - description: Normalized and obfuscated representative query text. + description: Normalized representative query text with literal values replaced by `?`. database: $ref: '#/components/schemas/DatabaseQueryPerformanceDatabase' role: type: string - description: Database role used for the query. + description: Postgres role that ran the query, such as `anon` or `authenticated` for RLS-enforced connections, `service_role`, the database owner role for full-access connections, or a role you created. `unknown` when the role no longer exists. calls: type: integer format: int64