



  

<!DOCTYPE html>
<html
  lang="en"
  
  data-color-mode="auto" data-light-theme="light" data-dark-theme="dark"
  data-a11y-animated-images="system" data-a11y-link-underlines="true"
  
  >




  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
  <link rel="preconnect" href="https://github.githubassets.com" crossorigin>
  <link rel="preconnect" href="https://avatars.githubusercontent.com">

<script type="importmap">{"imports":{"react":"https://github.githubassets.com/assets/react-e27d1b3e03961e68.js","react-dom":"https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js","react-dom/client":"https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js","react-is":"https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js","react-reconciler":"https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js","react/compiler-runtime":"https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js","react/jsx-dev-runtime":"https://github.githubassets.com/assets/react-jsx-dev-runtime-ea55d68667d559e5.js","react/jsx-runtime":"https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js","scheduler":"https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js"}}</script>
<meta name="react-profiling" content="0" data-turbo-transient="true" />
<meta name="react-import-map" content="react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@777f63f87cd0" data-turbo-track="reload" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-e27d1b3e03961e68.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js" />

  


  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="light" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-0f910d8806d5761b.css" /><link data-color-theme="light_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind_high_contrast-a7abd4d4c49ac593.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-5fc4c4a9cb41e596.css" /><link data-color-theme="light_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia_high_contrast-ed0cee9214dedabd.css" /><link data-color-theme="dark" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-78a2491d538dab5a.css" /><link data-color-theme="dark_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind_high_contrast-c26b63d7c532d0a2.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-a6f60cea68c08405.css" /><link data-color-theme="dark_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia_high_contrast-f66faf28b2ea18b6.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-6701f6218c53cf5b.css" /><link data-color-theme="dark_dimmed_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed_high_contrast-7037fa46ae124d97.css" />

  <style type="text/css">
    :root {
      --tab-size-preference: 4;
    }

    pre, code {
      tab-size: var(--tab-size-preference);
    }
  </style>

    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-97df7784617ce1ea.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-9be9fe6313f476af.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-62747e27e61258dc.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-7a418ea859d1654d.css" />
  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-72bd7d974b5ac1cc.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-4c5c0895f723f870.css" />

  

  <script type="application/json" id="client-env">{"locale":"en","featureFlags":["actions_caches_react_shell","actions_enable_background_steps","actions_new_hosted_runner_image_select_sizes_and_versions","actions_runners_react_shell","activity_diff_file_tree","activity_repos_file_tree","activity_repos_overview_header","activity_repos_overview_sidebar","agent_author_search_expansion","agent_author_search_expansion_ui_pulls","alternate_user_config_repo","async_conversion_coverage_enabled","billing_billable_licenses_cost_center_bucket_fix","billing_budget_expiration","billing_cost_center_list_assigned_resources","billing_discount_threshold_notification","code_quality_enablement_banner_targeting","code_quality_remove_preview","code_view_raf_sticky_lines","codespaces_prebuild_region_target_update","coding_agent_third_party_model_ui","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_automation_repo_mcp_servers","copilot_automations_pagination","copilot_base_model_policy_row","copilot_chat_auto_mode_v2","copilot_chat_clear_model_selection_for_default_change","copilot_chat_early_task_provisioning","copilot_chat_persist_session_drafts","copilot_chat_vision_dotcom_chat_ga_gate","copilot_css_textarea_autosize","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_removal_on_marketplace","copilot_fix_failed_workflows_all_skus","copilot_hide_hovercard","copilot_immersive_task_hyperlinking","copilot_mc_cli_resume_any_users_task","copilot_mission_control_agent_merge_fix_ci","copilot_mission_control_agent_merge_resolve_conflicts","copilot_mission_control_awps_batching","copilot_mission_control_early_stop","copilot_mission_control_managed_sandbox_environments","copilot_mission_control_needs_attention","copilot_mission_control_reasoning_effort","copilot_mission_control_sandbox_remote_bypass","copilot_mission_control_task_alive_updates","copilot_mission_control_task_sharing","copilot_org_policy_page_focus_mode","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_swe_agent_authorization_status_ui","copilot_swe_agent_automation_resource_scoped_writes","copilot_swe_agent_discussion_comment_trigger","copilot_swe_agent_discussion_opened_trigger","copilot_swe_agent_discussion_updated_trigger","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_issue_assigned_trigger","copilot_swe_agent_issue_comment_trigger","copilot_swe_agent_issue_labeled_trigger","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_pull_request_assigned_trigger","copilot_swe_agent_pull_request_comment_trigger","copilot_swe_agent_pull_request_labeled_trigger","copilot_swe_agent_pull_request_merged_trigger","copilot_swe_agent_pull_request_opened_trigger","copilot_swe_agent_pull_request_ready_for_review_trigger","copilot_swe_agent_pull_request_review_requested_trigger","copilot_swe_agent_pull_request_review_submitted_trigger","copilot_swe_agent_pull_request_synchronize_trigger","copilot_swe_agent_sub_issue_added_trigger","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_task_scoped_alive_channel","copilot_token_based_billing","copilot_unconfigured_is_inherited","copilot_user_can_upgrade_plan_field","copilot_web_integration_cutover","copilot_workbench_sunset_redirect","dashboard_agents_module_auth_token_check","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","fgpat_permissions_selector_redesign","glc_code_quality_repo_settings_workflow_config","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","in_product_messaging_datadog_monitoring","ipm_ubb_individual_budget_banner","issue_fields_multi_select","issue_inline_avatars","issue_pinned_views","issue_pinned_views_team_vs_personal","issue_relative_time_micro","issue_viewer_paved_path","issues_expanded_file_types","issues_hide_closed_sub_issues","issues_lazy_load_comment_box_suggestions","issues_react_chrome_container_query_fix","labels_archiving","labels_archiving_info","landing_pages_ninetailed","lifecycle_label_name_updates","marketing_cookie_consent_banner","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_queue_restricted_pushers_warning","merge_status_header_feedback","milestone_closed_issues_prioritization","octocaptcha_origin_optimization","primer_react_css_anchor_positioning","primer_react_merged_forwarded_refs","primer_react_timeline_list_semantics","prs_copilot_app_open_action","prs_css_anchor_positioning","pull_request_copilot_attribution_header","pull_request_overview_merge_control","pull_request_overview_panel_edit_description","pull_request_persister","pull_request_stacks_navigation_shortcuts","pull_request_virtualization_image_estimate","pull_request_virtualization_loader_batching","pull_request_virtualization_scroll_compensation","pull_request_virtualization_scroll_intent","quick_search_lazy_suggestions","react_blob_isolate_code_lines","react_blob_ssr_content_visibility","react_data_router_tanstack_allowed","react_logged_out_repository_header","react_query_props_with_key","react_sandbox_future_tanstack","repo_app_turbo","repo_issues_sidebar_layout","repo_pulls_dashboard_declutter","repo_pulls_dashboard_ga","repo_pulls_dashboard_persistence","repo_pulls_dashboard_sidebar_links","repos_contributors_limited_default_range","review_involves_filter","rule_ignored_file_paths","rulesets_actor_list_editor","sample_network_conn_type","security_center_artifact_filters_popover","see_who_reacted","semantic_similarity_duplicate_issue_detection","session_logs_ungroup_reasoning_text","set_sha256_on_repo_creation_form","site_banner_desktop_copilot_app","site_ghca_pixel_mona","site_github_app_ga_page","site_github_app_ga_page_highlight","site_github_app_mobile_native_share","site_global_banner_dev_days_attendee","site_global_nav_spark_models_removed","speculation_rules_ui_service","suggest_custom_property_values_copilot","suppress_automated_browser_vitals","swp_forms_disable_octocaptcha","thread_resolution_reason","update_issue_suggestions","viewscreen_sandbox","warn_inaccessible_attachments","webp_support","workstream_plugin_bootstrap"],"githubDomain":"https://github.com","copilotApiOverrideUrl":"https://api.githubcopilot.com","cmcApiUrl":"https://api.github.com/cmc_internal/api"}</script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/high-contrast-cookie-ecea76118deb7aaa.js"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-runtime-d9341e195bcec310.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-foundation-e30e053a2ec05810.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-runtime-43a736cfb17bfc3b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fetch-utilities-63626b86ca960a13.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ser-a0f837900b980022.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tp-daaf4baff8a79901.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/environment-98ea7e4e387ca729.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-runtime.7ee70a9cd769c13f.module.css" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/catalyst-42724bfdecdcf111.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/selector-observer-e8810f64c443fb9b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/relative-time-element-0417f617ad744a0d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/by-9da36843ba9d191d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ja9-9a1160b939f2cd52.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/3h-55903cf2303047ad.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hk-f1498fec45311acd.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jz5-7aa1ff0a0e750f41.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hj-1d800d09e9a8720a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j0-ccaf30a6d91f2f83.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/github-elements-8d654ca1a17effc5.js" defer="defer"></script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/element-registry-29480d8144d2807c.js" defer="defer"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/runtime-helpers-5e0b3ae3c4036207.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/aria-live-827ce46b7ade1744.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hotkey-9080b92ee55ecdce.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-core-181fffe35f64a86b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a9-c3ca0fbca57ec92e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/urv-054283cae3e84e4a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4t-b7957415f663bc13.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pb-1b8646f441999bcd.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/6n-afcf86ccabc4cad2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zj-1e9837c8e3c294ac.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ix-db979d3ffe7f4c37.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tw-dd6dc4caea8bef08.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/qyq-3e7962e375ef7004.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/bcs-f35fbf8e2ea6dbe7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7l-560ecaad1259d656.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jl-e8dc4e5499c418bf.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/85-45c9403416d395d4.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/behaviors-1f968fe0d5fd1163.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-core.be84e87b659d3b98.module.css" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-menu-78b435403f678765.js" defer="defer"></script>
  
  <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/primer-react-b8b1f4173243006b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/nc-602186f274c7f83c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/qmp-16b258ea4c9e9207.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j6-e2974066e87682ac.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/t7l-07b4d1555e9567f3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4u-1fa5e65b146a8e59.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s0-ef17fe8bd07a3b4d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/y5-1b30b762023d3e89.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/n4u-f85b84521e1734c3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j8s-48e0fe20eefd980e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/la-27679061f16e1495.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/iu-58ac501be176845a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/gru-90582bf85fdae29b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a0-62a325e8a801c241.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vy-77fa71d04f920b10.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/gb-6acc3941ce05eb8d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/f7-0866cc20e1a6e4a3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/csq-a4622df32bd3f47f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ssg-cf5ac52afa782913.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/lk-079e9de06c3be0af.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/x00-344c6e66a12fe4b8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wsu-447e9f95188c7974.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/038-7e759dd92b23180b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/qmq-b7fd747ac0dec1dc.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hwq-eba66f3e802ed05e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/lcf-c3749f061b720d7a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/meu-720cfd8779ef970d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tg-0262af28cee91950.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/is-72fb9279eae70f4e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/dc-9a4f5284b4d6b55b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/w9-183da1d030133670.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r09-6a8e9e38bd26e4b8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/642-0c34f01503252c51.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/45z-500ac78bc30b1f49.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/61-99828705784c9574.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ioz-e202cd57dfb0dbae.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/kwg-1568470998026677.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/1mc-0231984e8f3f4958.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pc-986abafaf53b769e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/1e-f3794268c20cd18d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/uu-6b8bc874d43973a0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/2sj-a0b3d11863f57a1e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/oj-79a85dac88e9d3f4.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ys-eeb95a3084a8716b.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-view-638da8f262df652d.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/45z.922f816fb2d6b268.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/oj.ecb4903dbaae6412.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-view.eb9a2f2a033c6ffd.module.css" />


  <title>dstack/sdk/python/README.md at next · Dstack-TEE/dstack · GitHub</title>



  <meta name="route-pattern" content="/:user_id/:repository/blob/*name(/*path)" data-turbo-transient>
  <meta name="route-controller" content="blob" data-turbo-transient>
  <meta name="route-action" content="show" data-turbo-transient>
  <meta name="fetch-nonce" content="v2:a313d473-2654-72f2-ffb9-4733d05bfa95">

    
  <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb">


  <meta name="request-id" content="EA88:5ABED:3A65950:4B528BD:6AC8B970" data-pjax-transient="true"/><meta name="html-safe-nonce" content="d1d59ba13a8b19fe6d12cce8273adeb51831d2d8d4e69e362a5143207458b6c0" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFQTg4OjVBQkVEOjNBNjU5NTA6NEI1MjhCRDo2QUM4Qjk3MCIsInZpc2l0b3JfaWQiOiIyNDUyNTE0MzA0ODYxNjE3NzYiLCJyZWdpb25fZWRnZSI6ImZyYSIsInJlZ2lvbl9yZW5kZXIiOiJmcmEifQ==" data-pjax-transient="true"/><meta name="visitor-hmac" content="ae2957a4bc8fe10e56ed2effa8d34c685781c3612ee4a6210356e984ae9879d4" data-pjax-transient="true"/>


    <meta name="hovercard-subject-tag" content="repository:856700396" data-turbo-transient>


  <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" />
  

  <meta name="selected-link" value="repo_source" data-turbo-transient>
  <link rel="assets" href="https://github.githubassets.com/">

    <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I">

<meta name="octolytics-url" content="https://collector.github.com/github/collect" />





  <meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-turbo-transient="true" />

  




    <meta name="user-login" content="">

  

    <meta name="viewport" content="width=device-width">

    

      <meta name="description" content="Open framework for confidential AI. Contribute to Dstack-TEE/dstack development by creating an account on GitHub.">

      <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">

    <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
    <meta property="fb:app_id" content="1401488693436528">
    <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/Dstack-TEE/dstack/blob/next/sdk/python/README.md" />

      <meta name="twitter:image" content="https://opengraph.githubassets.com/a935ff6fbd218c27bb8d984a32f28b49877235830d76de88eb671612fd5fab34/Dstack-TEE/dstack" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="dstack/sdk/python/README.md at next · Dstack-TEE/dstack" /><meta name="twitter:description" content="Open framework for confidential AI. Contribute to Dstack-TEE/dstack development by creating an account on GitHub." />
  <meta property="og:image" content="https://opengraph.githubassets.com/a935ff6fbd218c27bb8d984a32f28b49877235830d76de88eb671612fd5fab34/Dstack-TEE/dstack" /><meta property="og:image:alt" content="Open framework for confidential AI. Contribute to Dstack-TEE/dstack development by creating an account on GitHub." /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="600" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="dstack/sdk/python/README.md at next · Dstack-TEE/dstack" /><meta property="og:url" content="https://github.com/Dstack-TEE/dstack/blob/next/sdk/python/README.md" /><meta property="og:description" content="Open framework for confidential AI. Contribute to Dstack-TEE/dstack development by creating an account on GitHub." />
  




      <meta name="hostname" content="github.com">



        <meta name="expected-hostname" content="github.com">


  <meta http-equiv="x-pjax-version" content="c169bf62ec00f7c94e993c61456b435cddf5ddc52128710c7c3128a129884d1c" data-turbo-track="reload">
  <meta http-equiv="x-pjax-csp-version" content="c4a65e47b0c850e1157ae8e66298070851d7e3b558038de5a3b4ff7a93e630ed" data-turbo-track="reload">
  <meta http-equiv="x-pjax-css-version" content="1ff3f1d4e1abd61f6f135b47d3b815e2f7169f8dd418f0118c6b1cf4de6cbc86" data-turbo-track="reload">
  <meta http-equiv="x-pjax-js-version" content="e0f90f2d9e13b9b16474d2e1f37fc82b0fbd41078cb4ed8dd0927ffa74bcd802" data-turbo-track="reload">

  <meta name="turbo-cache-control" content="no-preview" data-turbo-transient="">

      <meta name="turbo-cache-control" content="no-cache" data-turbo-transient>

    <meta data-hydrostats="publish">

  <meta name="go-import" content="github.com/Dstack-TEE/dstack git https://github.com/Dstack-TEE/dstack.git">

  <meta name="octolytics-dimension-user_id" content="187594727" /><meta name="octolytics-dimension-user_login" content="Dstack-TEE" /><meta name="octolytics-dimension-repository_id" content="856700396" /><meta name="octolytics-dimension-repository_nwo" content="Dstack-TEE/dstack" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="856700396" /><meta name="octolytics-dimension-repository_network_root_nwo" content="Dstack-TEE/dstack" />
  



    

    <meta name="turbo-body-classes" content="logged-out env-production page-responsive">
  <meta name="disable-turbo" content="false">


  <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">


  <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">

  <meta name="release" content="e098a98aecf5b75ff5c86b255440b070d88fd8f9" data-turbo-track="reload">
  <meta name="ui-target" content="full">

  <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000">
  <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png">
  <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon">

<meta name="theme-color" content="#1e2327">
<meta name="color-scheme" content="light dark" />


  <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials">

  </head>

  <body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
    <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
      <div id="__primerPortalRoot__" style="z-index: 1000; position: absolute; width: 100%;" data-turbo-permanent></div>
      

    <div class="position-relative header-wrapper js-header-wrapper ">
      <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 tmp-py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a>

      <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full">
    <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span>
</span>      
      <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/no-1cf75929f17e3028.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-3ccb6dec8639ef3e.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog.b7674213eb62f489.module.css" />

<react-partial
  partial-name="keyboard-shortcuts-dialog"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>





      

          <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-install-banner-partial-3a65ea248a6c8f3f.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-install-banner-partial.566d73e5e22ba1de.module.css" />

<react-partial
  partial-name="app-install-banner-partial"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>


          

                <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/2lp-a40e70e520dbe650.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/rwd-7b2c7e3d5830b9e9.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fz5-26e9f173be523540.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jag-e8b94ef4bf214893.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/l19-ab9291460ccba23f.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5nx-54af91826ad57196.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zn-f168d65b85b3e44a.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/marketing-header-d5088a04768fe17c.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-brand-css.05b219cdb8e80c43.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/zn.9fc2e923e926de87.module.css" />

<react-partial
  partial-name="marketing-header"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"color_mode":"dark","logged_in":false,"marketing_page":false,"home_path":"/","login_path":"/login?return_to=https%3A%2F%2Fgithub.com%2FDstack-TEE%2Fdstack%2Fblob%2Fnext%2Fsdk%2Fpython%2FREADME.md","signup_path":"/signup?ref_cta=Sign+up\u0026ref_loc=header+logged+out\u0026ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow\u0026source=header-repo\u0026source_repo=Dstack-TEE%2Fdstack","signup_enabled":true,"is_signup_controller":false,"show_search_and_nav":true,"hide_search":false,"private_mode_enabled":false,"should_use_dotcom_links":true,"auth_hydro_click":"{\"event_type\":\"authentication.click\",\"payload\":{\"location_in_page\":\"site header menu\",\"repository_id\":null,\"auth_type\":\"SIGN_UP\",\"originating_url\":\"https://github.com/Dstack-TEE/dstack/blob/next/sdk/python/README.md\",\"user_id\":null}}","auth_hydro_click_hmac":"f3c16360b2248b0096ae6df44baa504030785fb5aefa3fda5f70bbc6fcca4b54","overlay":false,"fixed":false}}</script>
  <div data-target="react-partial.reactRoot"><div data-color-mode="dark" data-light-theme="light" data-dark-theme="dark"><header class="MarketingHeader-module__root__Tk7n3 HeaderMktg header-logged-out" role="banner" data-marketing-header="true" data-color-mode="dark" data-light-theme="light" data-dark-theme="dark" data-is-top="true"><h2 class="MarketingHeader-module__visuallyHidden__sqKsl">Navigation Menu</h2><button type="button" class="MarketingHeader-module__backdrop__sw4RU" aria-label="Close navigation menu"></button><div class="MarketingHeader-module__bar__mBSyE"><div class="MarketingHeader-module__topRow__yeury"><div class="MarketingHeader-module__toggleSlot__hDxbh"><button type="button" class="HeaderMenuToggle-module__toggle__i8EiC" aria-label="Toggle navigation" aria-expanded="false"><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span></button></div><a href="/" aria-label="Homepage" class="HeaderLogo-module__logo__UFyHI" data-analytics-event="{&quot;action&quot;:&quot;homepage&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;logo&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;homepage_link_logo_header&quot;}"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github" viewBox="0 0 24 24" width="32" height="32" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path></svg></a><div class="AuthCTAs-module__mobileActions__NNzeV"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/login?return_to=https%3A%2F%2Fgithub.com%2FDstack-TEE%2Fdstack%2Fblob%2Fnext%2Fsdk%2Fpython%2FREADME.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/Dstack-TEE/dstack/blob/next/sdk/python/README.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="f3c16360b2248b0096ae6df44baa504030785fb5aefa3fda5f70bbc6fcca4b54"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_3dd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_3dd_">Appearance settings</div></div></div><div class="MarketingHeader-module__menu__GIy3y"><div class="MarketingHeader-module__menuWrapper__owstH"><nav class="MarketingNavigation-module__nav__W0KYY" aria-label="Global"><ul class="MarketingNavigation-module__list__tFbMb"><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_nd_">Platform<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5knd_">AI CODE CREATION</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot" data-analytics-event="{&quot;action&quot;:&quot;github_copilot&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>GitHub Copilot</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Write better code with AI</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/ai/github-app" data-analytics-event="{&quot;action&quot;:&quot;github_copilot_app&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_app_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.766 11.328c-2.063-.25-3.516-1.734-3.516-3.656 0-.781.281-1.625.75-2.188-.203-.515-.172-1.609.063-2.062.625-.078 1.468.25 1.968.703.594-.187 1.219-.281 1.985-.281.765 0 1.39.094 1.953.265.484-.437 1.344-.765 1.969-.687.218.422.25 1.515.046 2.047.5.593.766 1.39.766 2.203 0 1.922-1.453 3.375-3.547 3.64.531.344.89 1.094.89 1.954v1.625c0 .468.391.734.86.547C13.781 14.359 16 11.53 16 8.03 16 3.61 12.406 0 7.984 0 3.563 0 0 3.61 0 8.031a7.88 7.88 0 0 0 5.172 7.422c.422.156.828-.125.828-.547v-1.25c-.219.094-.5.156-.75.156-1.031 0-1.64-.562-2.078-1.609-.172-.422-.36-.672-.719-.719-.187-.015-.25-.093-.25-.187 0-.188.313-.328.625-.328.453 0 .844.281 1.25.86.313.452.64.655 1.031.655s.641-.14 1-.5c.266-.265.47-.5.657-.656"></path></svg>GitHub Copilot app</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Direct agents from issue to merge</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/mcp" data-analytics-event="{&quot;action&quot;:&quot;mcp_registry&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;mcp_registry_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mcp NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.52 1.12a3.578 3.578 0 0 1 6.078 2.98 3.578 3.578 0 0 1 2.982 6.08l-3.292 3.293a.252.252 0 0 0 0 .354l.843.843a.749.749 0 1 1-1.06 1.06l-.844-.843a1.75 1.75 0 0 1 0-2.474L13.52 9.12a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0L7.731 9.03A.75.75 0 0 1 6.67 7.97l2.85-2.85a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0l-4.799 4.8A.75.75 0 0 1 .72 5.92Z"></path><path d="M7.52 3.12a.749.749 0 1 1 1.06 1.06L5.731 7.03A2.079 2.079 0 0 0 8.67 9.97l2.85-2.85a.749.749 0 1 1 1.06 1.06l-2.849 2.85A3.578 3.578 0 0 1 4.67 5.97Z"></path></svg>MCP Registry</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Integrate external tools</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9knd_">DEVELOPER WORKFLOWS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/actions" data-analytics-event="{&quot;action&quot;:&quot;actions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;actions_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-workflow NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path></svg>Actions</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Automate any workflow</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/codespaces" data-analytics-event="{&quot;action&quot;:&quot;codespaces&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;codespaces_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codespaces NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path></svg>Codespaces</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Instant dev environments</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/issues" data-analytics-event="{&quot;action&quot;:&quot;issues&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;issues_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg>Issues</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Plan and track work</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-review" data-analytics-event="{&quot;action&quot;:&quot;code_review&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_review_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg>Code Review</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Manage code changes</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-quality" data-analytics-event="{&quot;action&quot;:&quot;code_quality&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_quality_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codescan-checkmark NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.28 6.28a.75.75 0 1 0-1.06-1.06L6.25 8.19l-.97-.97a.75.75 0 0 0-1.06 1.06l1.5 1.5a.75.75 0 0 0 1.06 0l3.5-3.5Z"></path><path d="M7.5 15a7.5 7.5 0 1 1 5.807-2.754l2.473 2.474a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2.474-2.473A7.472 7.472 0 0 1 7.5 15Zm0-13.5a6 6 0 1 0 4.094 10.386.748.748 0 0 1 .293-.292 6.002 6.002 0 0 0 1.117-6.486A6.002 6.002 0 0 0 7.5 1.5Z"></path></svg>Code Quality</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enforce quality at merge</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dknd_">APPLICATION SECURITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Find and fix vulnerabilities</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/code-security" data-analytics-event="{&quot;action&quot;:&quot;code_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code-square NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>Code security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Secure your code as you build</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/secret-protection" data-analytics-event="{&quot;action&quot;:&quot;secret_protection&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;secret_protection_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-lock NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M4 4a4 4 0 0 1 8 0v2h.25c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 12.25 15h-8.5A1.75 1.75 0 0 1 2 13.25v-5.5C2 6.784 2.784 6 3.75 6H4Zm8.25 3.5h-8.5a.25.25 0 0 0-.25.25v5.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25ZM10.5 6V4a2.5 2.5 0 1 0-5 0v2Z"></path></svg>Secret protection</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Stop leaks before they start</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ NavGroup-module__hasSeparator__FnMrN"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_hknd_">EXPLORE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_hknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/why-github" data-analytics-event="{&quot;action&quot;:&quot;why_github&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;why_github_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Why GitHub</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog" data-analytics-event="{&quot;action&quot;:&quot;blog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;blog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Blog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog/changelog" data-analytics-event="{&quot;action&quot;:&quot;changelog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;changelog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Changelog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/marketplace" data-analytics-event="{&quot;action&quot;:&quot;marketplace&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;marketplace_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Marketplace</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/features" data-analytics-event="{&quot;action&quot;:&quot;view_all_features&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_features_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all features</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_17d_">Solutions<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_17d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5l7d_">BY COMPANY SIZE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprises&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprises_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Enterprises</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/team" data-analytics-event="{&quot;action&quot;:&quot;small_and_medium_teams&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;small_and_medium_teams_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Small and medium teams</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise/startups" data-analytics-event="{&quot;action&quot;:&quot;startups&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;startups_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Startups</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/nonprofits" data-analytics-event="{&quot;action&quot;:&quot;nonprofits&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;nonprofits_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Nonprofits</span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9l7d_">BY USE CASE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/app-modernization" data-analytics-event="{&quot;action&quot;:&quot;app_modernization&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;app_modernization_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">App Modernization</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devsecops" data-analytics-event="{&quot;action&quot;:&quot;devsecops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devsecops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevSecOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/ci-cd" data-analytics-event="{&quot;action&quot;:&quot;ci/cd&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ci/cd_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">CI/CD</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/use-case" data-analytics-event="{&quot;action&quot;:&quot;view_all_use_cases&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_use_cases_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all use cases</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dl7d_">BY INDUSTRY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dl7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/healthcare" data-analytics-event="{&quot;action&quot;:&quot;healthcare&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;healthcare_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Healthcare</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/financial-services" data-analytics-event="{&quot;action&quot;:&quot;financial_services&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;financial_services_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Financial services</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/manufacturing" data-analytics-event="{&quot;action&quot;:&quot;manufacturing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;manufacturing_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Manufacturing</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/government" data-analytics-event="{&quot;action&quot;:&quot;government&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;government_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Government</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/industry" data-analytics-event="{&quot;action&quot;:&quot;view_all_industries&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_industries_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all industries</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions" data-analytics-event="{&quot;action&quot;:&quot;view_all_solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_solutions_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all solutions</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_1nd_">Resources<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_1nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5lnd_">EXPLORE BY TOPIC</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=ai" data-analytics-event="{&quot;action&quot;:&quot;ai&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ai_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">AI</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=software-development" data-analytics-event="{&quot;action&quot;:&quot;software_development&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;software_development_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Software Development</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=security" data-analytics-event="{&quot;action&quot;:&quot;security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources/articles" data-analytics-event="{&quot;action&quot;:&quot;view_all_topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_topics_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all topics</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9lnd_">EXPLORE BY TYPE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/customer-stories" data-analytics-event="{&quot;action&quot;:&quot;customer_stories&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_stories_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer stories</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/events" data-analytics-event="{&quot;action&quot;:&quot;events__webinars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;events__webinars_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Events &amp; webinars</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/whitepapers" data-analytics-event="{&quot;action&quot;:&quot;ebooks__reports&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ebooks__reports_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Ebooks &amp; reports</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/executive-insights" data-analytics-event="{&quot;action&quot;:&quot;business_insights&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;business_insights_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Business insights</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://skills.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_skills&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_skills_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Skills</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dlnd_">SUPPORT &amp; SERVICES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dlnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://support.github.com" data-analytics-event="{&quot;action&quot;:&quot;customer_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_support_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer support</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/orgs/community/discussions" data-analytics-event="{&quot;action&quot;:&quot;community_forum&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;community_forum_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Community forum</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trust-center" data-analytics-event="{&quot;action&quot;:&quot;trust_center&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trust_center_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trust center</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/partners" data-analytics-event="{&quot;action&quot;:&quot;partners&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;partners_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Partners</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources" data-analytics-event="{&quot;action&quot;:&quot;view_all_resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_resources_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all resources</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_27d_">Open Source<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_27d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5m7d_">COMMUNITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/open-source/sponsors" data-analytics-event="{&quot;action&quot;:&quot;github_sponsors&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_sponsors_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sponsor-tiers NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.586 1C12.268 1 13.5 2.37 13.5 4.25c0 1.745-.996 3.359-2.622 4.831-.166.15-.336.297-.509.438l1.116 5.584a.75.75 0 0 1-.991.852l-2.409-.876a.25.25 0 0 0-.17 0l-2.409.876a.75.75 0 0 1-.991-.852L5.63 9.519a13.78 13.78 0 0 1-.51-.438C3.497 7.609 2.5 5.995 2.5 4.25 2.5 2.37 3.732 1 5.414 1c.963 0 1.843.403 2.474 1.073L8 2.198l.112-.125a3.385 3.385 0 0 1 2.283-1.068L10.586 1Zm-3.621 9.495-.718 3.594 1.155-.42a1.75 1.75 0 0 1 1.028-.051l.168.051 1.154.42-.718-3.592c-.199.13-.37.235-.505.314l-.169.097a.75.75 0 0 1-.72 0 9.54 9.54 0 0 1-.515-.308l-.16-.105ZM10.586 2.5c-.863 0-1.611.58-1.866 1.459-.209.721-1.231.721-1.44 0C7.025 3.08 6.277 2.5 5.414 2.5 4.598 2.5 4 3.165 4 4.25c0 1.23.786 2.504 2.128 3.719.49.443 1.018.846 1.546 1.198l.325.21.076-.047.251-.163a13.341 13.341 0 0 0 1.546-1.198C11.214 6.754 12 5.479 12 4.25c0-1.085-.598-1.75-1.414-1.75Z"></path></svg>GitHub Sponsors</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Fund open source developers</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9m7d_">PROGRAMS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://securitylab.github.com" data-analytics-event="{&quot;action&quot;:&quot;security_lab&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_lab_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security Lab</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://maintainers.github.com" data-analytics-event="{&quot;action&quot;:&quot;maintainer_community&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;maintainer_community_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Maintainer Community</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://stars.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_stars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_stars_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Stars</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://archiveprogram.github.com" data-analytics-event="{&quot;action&quot;:&quot;archive_program&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;archive_program_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Archive Program</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dm7d_">REPOSITORIES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dm7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/topics" data-analytics-event="{&quot;action&quot;:&quot;topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;topics_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Topics</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trending" data-analytics-event="{&quot;action&quot;:&quot;trending&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trending_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trending</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/collections" data-analytics-event="{&quot;action&quot;:&quot;collections&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;collections_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Collections</span></a></li></ul></div></li></ul></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_2nd_">Enterprise<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_2nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5mnd_">ENTERPRISE SOLUTIONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprise_platform&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprise_platform_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-stack NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.122.392a1.75 1.75 0 0 1 1.756 0l5.003 2.902c.83.481.83 1.68 0 2.162L8.878 8.358a1.75 1.75 0 0 1-1.756 0L2.119 5.456a1.251 1.251 0 0 1 0-2.162ZM8.125 1.69a.248.248 0 0 0-.25 0l-4.63 2.685 4.63 2.685a.248.248 0 0 0 .25 0l4.63-2.685ZM1.601 7.789a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0L1.874 8.814A.75.75 0 0 1 1.6 7.789Zm0 3.5a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0l-5.248-3.044a.75.75 0 0 1-.273-1.025Z"></path></svg>Enterprise platform</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">AI-powered developer platform</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9mnd_">AVAILABLE ADD-ONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade security features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot/copilot-business" data-analytics-event="{&quot;action&quot;:&quot;copilot_for_business&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;copilot_for_business_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>Copilot for Business</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade AI features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise/premium-support" data-analytics-event="{&quot;action&quot;:&quot;premium_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;premium_support_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path></svg>Premium Support</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade 24/7 support</span></span></a></li></ul></div></li></ul></div></div></li><li><a href="https://github.com/pricing" data-analytics-event="{&quot;action&quot;:&quot;pricing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;pricing&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;pricing_link_pricing_navbar&quot;}" class="MarketingNavigation-module__navLink__hUomM">Pricing</a></li></ul></nav><div class="MarketingHeader-module__ctaContainer__tBmPz"><div class="HeaderSearch-module__searchSlot__oVOUS"><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderSearch-module__trigger__zsF9q" type="button" aria-haspopup="dialog" aria-expanded="false" aria-label="Search or jump to, type / to search" data-analytics-event="{&quot;action&quot;:&quot;searchbar&quot;,&quot;tag&quot;:&quot;input&quot;,&quot;context&quot;:&quot;global&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;searchbar_input_global_navbar&quot;}"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"><span class="HeaderSearch-module__content__kMpxU"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search HeaderSearch-module__icon__wcrHX" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg><span class="HeaderSearch-module__label__d1iWG">Search</span><kbd class="HeaderSearch-module__kbd__HNG0o" aria-hidden="true">/</kbd></span></span></span></button><div class="d-none"></div></div><div class="AuthCTAs-module__signInWrap__q2P60"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq AuthCTAs-module__desktopActionGap__UZuXT AuthCTAs-module__hiddenBelowLg__BfKBw" href="/login?return_to=https%3A%2F%2Fgithub.com%2FDstack-TEE%2Fdstack%2Fblob%2Fnext%2Fsdk%2Fpython%2FREADME.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/Dstack-TEE/dstack/blob/next/sdk/python/README.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="f3c16360b2248b0096ae6df44baa504030785fb5aefa3fda5f70bbc6fcca4b54"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a></div><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--secondary___gHnw_ Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/signup?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow&amp;source=header-repo&amp;source_repo=Dstack-TEE%2Fdstack" data-analytics-event="{&quot;action&quot;:&quot;sign_up&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_up_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/Dstack-TEE/dstack/blob/next/sdk/python/README.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="f3c16360b2248b0096ae6df44baa504030785fb5aefa3fda5f70bbc6fcca4b54"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-secondary___eJ0_a">Sign up</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_fbd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_fbd_">Appearance settings</div></div></div></div></div><div class="MarketingHeader-module__bottomBorder__uZT38" aria-hidden="true"></div></header></div></div>
</react-partial>



      <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full">
  
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
        <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>

    <button id="icon-button-4881d4cd-e644-48a1-a07b-b42b1b0aed34" aria-labelledby="tooltip-e2737fae-e95a-4d42-8b9f-18134314b0d4" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close">  <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
</button><tool-tip id="tooltip-e2737fae-e95a-4d42-8b9f-18134314b0d4" for="icon-button-4881d4cd-e644-48a1-a07b-b42b1b0aed34" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip>


  
</div>
    </div>

  <div id="start-of-content" class="show-on-focus"></div>








    <div id="js-flash-container" class="flash-container" data-turbo-replace>






  <template class="js-flash-template">
    
<div class="flash flash-full   {{ className }}">
  <div >
    <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    <div aria-atomic="true" role="alert" class="js-flash-alert">
      
      <div>{{ message }}</div>

    </div>
  </div>
</div>
  </template>
</div>


    






  <div
    class="application-main "
    data-commit-hovercards-enabled
    data-discussion-hovercards-enabled
    data-issue-and-pr-hovercards-enabled
    data-project-hovercards-enabled
  >
        <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class="">
    <main id="js-repo-pjax-container" >
      
      
    


    








  

    <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ym-4c4d2b70d5b17037.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/mng-af5547fcfd291f53.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/t5-8ffaa093c3420000.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j24-43443b443f213349.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vw-9a8839ba1b0498ae.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ac-330683e1e1b3028b.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/f4t-6a4e2ce1a3f6bcd5.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/36-e7bb48b69e86f71b.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tps-84accc305677e828.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/e8k-f5cca939ef074708.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/nx-e5a4a427b19a5363.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/3s-7ab43a292b98ba5f.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a1w-8b2cb4a1188ed337.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/nr-79588a4a563e6198.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/global-nav-bar-3f93ce7e68bc7168.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/45z.922f816fb2d6b268.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-nav-bar.9f560a86de809a16.module.css" />

<react-partial
  partial-name="global-nav-bar"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"contextRegion":{"crumbs":[{"crumb_type":"organization","label":"Dstack-TEE","is_root":false,"href":"/Dstack-TEE"},{"crumb_type":"repository","label":"dstack","is_root":false,"href":"/Dstack-TEE/dstack"}],"localNavigation":[{"id":"code","icon":"code","label":"Code","href":"/Dstack-TEE/dstack","selectedLinks":["repo_source","repo_downloads","repo_commits","repo_releases","repo_tags","repo_branches","repo_packages","repo_deployments","repo_attestations"],"popoverTarget":false,"commandId":"repositories:go-to-code","reactNav":{"appTarget":"code-view","anchor":"code-view-repo-link"},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"issues","icon":"issue-opened","label":"Issues","href":"/Dstack-TEE/dstack/issues","selectedLinks":["repo_issues","repo_labels","repo_milestones"],"count":70,"popoverTarget":false,"commandId":"repositories:go-to-issues","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"pull-requests","icon":"git-pull-request","label":"Pull requests","href":"/Dstack-TEE/dstack/pulls","selectedLinks":["repo_pulls","checks"],"count":34,"popoverTarget":false,"commandId":"repositories:go-to-pull-requests","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"discussions","icon":"comment-discussion","label":"Discussions","href":"/Dstack-TEE/dstack/discussions","selectedLinks":["repo_discussions"],"popoverTarget":false,"commandId":"repositories:go-to-discussions","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"actions","icon":"play","label":"Actions","href":"/Dstack-TEE/dstack/actions","selectedLinks":["repo_actions"],"popoverTarget":false,"commandId":"repositories:go-to-actions","reactNav":{"appTarget":"actions-workflows","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"projects","icon":"table","label":"Projects","href":"/Dstack-TEE/dstack/projects","selectedLinks":["repo_projects","new_repo_project","repo_project"],"popoverTarget":false,"commandId":"repositories:go-to-projects","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"security-and-quality","icon":"shield","label":"Security and quality","href":"/Dstack-TEE/dstack/security","selectedLinks":["security","overview","alerts","policy","token_scanning","code_scanning"],"count":1,"popoverTarget":false,"commandId":"repositories:go-to-security","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"insights","icon":"graph","label":"Insights","href":"/Dstack-TEE/dstack/pulse","selectedLinks":["repo_graphs","repo_contributors","dependency_graph","dependabot_updates","pulse","people","community"],"popoverTarget":false,"commandId":"repositories:go-to-insights","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}}],"localNavigationUpdateChannel":null,"selectedLink":"repo_source"},"owner":null,"headerLogo":{"href":"/","aria-label":"Homepage "},"notifications":{"indicatorMode":"disabled","websocketChannel":null,"fetchIndicatorSrc":"/notifications/indicator","fetchIndicatorEnabled":false},"issues":{"href":"/issues"},"pulls":{"href":"/pulls"},"contributedRepos":{"href":"/repos"},"copilot":{"show":false,"showAgentsButton":false,"showRelaunchAnnouncement":false,"copilotChatUrl":null,"copilotApiUrl":"https://api.githubcopilot.com"},"search":{"show":true,"showCommandPalette":false,"isSearchPage":false,"isJumpToSearch":false,"searchContext":{"scope":"repo:Dstack-TEE/dstack","current_repo_name":"dstack","current_repo_nwo":"Dstack-TEE/dstack","current_repo_org":"Dstack-TEE","user_id":"Dstack-TEE"}},"commandPalette":null,"enterpriseBar":{"show":false},"globalTransactionalMessage":[],"payloadsUrl":"/_global-navigation/payloads.json?can_toggle_site_admin_and_employee_status=0\u0026is_admin_mode_on=0\u0026is_ui_opted_out=0\u0026show_ui_opt_out=0\u0026v=6","contextRegionUrl":"/_global-navigation/context-region.json"}}</script>
  <div data-target="react-partial.reactRoot"><header aria-label="Global navigation menu" data-component="Stack" class="GlobalNav styles-module__appHeader__YzYWk prc-Stack-Stack-UQ9k6" data-gap="none" data-direction="vertical" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="none"><div data-component="Stack" class="prc-Stack-Stack-UQ9k6" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="center" data-padding="none"><div data-testid="top-nav-center" data-component="Stack" class="styles-module__center__R3QRv styles-module__withLocalNavigation__rjTJ_ GlobalNavBar-module__loggedOut__Jv1rk prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="normal"><nav class="styles-module__contextRegion__VbSp2 prc-Breadcrumbs-BreadcrumbsBase-3Gb-B" aria-label="Breadcrumbs" data-overflow="menu" data-variant="normal" data-component="Breadcrumbs"><ol class="prc-Breadcrumbs-BreadcrumbsList-BKjpe"><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/Dstack-TEE" data-discover="true"><span class="">Dstack-TEE</span></a></li><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/Dstack-TEE/dstack" data-discover="true"><span class="styles-module__contextCrumbLast__tI2e3">dstack</span></a></li></ol></nav></div><div data-testid="top-nav-right" data-component="Stack" class="styles-module__right__mlBQg styles-module__withLocalNavigation__rjTJ_ styles-module__rightWithResponsiveCreateButton__SKn2W prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="start" data-padding="normal"></div></div><h2 class="prc-src-InternalVisuallyHidden-2YaI6">Repository navigation</h2><nav class="prc-components-UnderlineWrapper-eT-Yj prc-UnderlineNav-UnderlineWrapper-GWONT LocalNavigation-module__LocalNavigation__b0Xc0" aria-label="Repository" data-variant="inset" data-overflow-mode="wrap" data-hide-icons-breakpoint="medium"><ul class="prc-UnderlineNav-ItemsList-oj8gN prc-components-UnderlineItemList-xKlKC" role="list"><li role="presentation" aria-hidden="true" class="prc-UnderlineNav-WrapSpacer--aLgz"></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a aria-current="page" data-tab-item="code" data-react-nav="code-view" data-react-nav-anchor="code-view-repo-link" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg></span><span data-component="text" data-content="Code">Code</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="issues" data-react-nav="repo" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack/issues" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg></span><span data-component="text" data-content="Issues">Issues</span><span data-component="counter"><span aria-hidden="true" data-variant="secondary" data-component="CounterLabel" class="prc-CounterLabel-CounterLabel-X-kRU">70</span><span class="prc-VisuallyHidden-VisuallyHidden-Q0qSB"> (<!-- -->70<!-- -->)</span></span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="pull-requests" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack/pulls" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-pull-request" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path></svg></span><span data-component="text" data-content="Pull requests">Pull requests</span><span data-component="counter"><span aria-hidden="true" data-variant="secondary" data-component="CounterLabel" class="prc-CounterLabel-CounterLabel-X-kRU">34</span><span class="prc-VisuallyHidden-VisuallyHidden-Q0qSB"> (<!-- -->34<!-- -->)</span></span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="discussions" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack/discussions" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path></svg></span><span data-component="text" data-content="Discussions">Discussions</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="actions" data-react-nav="actions-workflows" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack/actions" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-play" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path></svg></span><span data-component="text" data-content="Actions">Actions</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="projects" data-react-nav="repo" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack/projects" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-table" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path></svg></span><span data-component="text" data-content="Projects">Projects</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="security-and-quality" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack/security" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg></span><span data-component="text" data-content="Security and quality">Security and quality</span><span data-component="counter"><span aria-hidden="true" data-variant="secondary" data-component="CounterLabel" class="prc-CounterLabel-CounterLabel-X-kRU">1</span><span class="prc-VisuallyHidden-VisuallyHidden-Q0qSB"> (<!-- -->1<!-- -->)</span></span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="insights" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/Dstack-TEE/dstack/pulse" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-graph" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg></span><span data-component="text" data-content="Insights">Insights</span></a></li></ul><div class="prc-UnderlineNav-MoreButtonContainer-Dnrq6"><div class="prc-UnderlineNav-MoreButtonDivider-dN0a-"></div><button data-component="overflow-menu-button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk prc-UnderlineNav-MoreButton-Y8soj" data-loading="false" data-size="medium" data-variant="invisible" id="_R_2ktl_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3"><span>More<span class="prc-src-InternalVisuallyHidden-2YaI6"> items</span></span></span></span><span data-component="trailingAction" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></button></div></nav><div class="d-none"></div></header></div>
</react-partial>


  



<turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class="">
    <div id="repo-content-pjax-container" class="repository-content " >
    



    
      
    








<react-app
  app-name="code-view"
  initial-path="/Dstack-TEE/dstack/blob/next/sdk/python/README.md"
  style="display: block; min-height: calc(100vh - 64px);"
  data-attempted-ssr="true"
  data-ssr="true"
  data-lazy="false"
  data-alternate="false"
  data-data-router-enabled="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-app.embeddedData">{"payload":{"codeViewBlobRoute":{"csv":null,"csvError":null,"headerInfo":{"toc":[{"level":1,"text":"dstack SDK for Python","anchor":"dstack-sdk-for-python","htmlText":"dstack SDK for Python"},{"level":2,"text":"The default client speaks v1","anchor":"the-default-client-speaks-v1","htmlText":"The default client speaks v1"},{"level":2,"text":"Installation","anchor":"installation","htmlText":"Installation"},{"level":2,"text":"Quick Start","anchor":"quick-start","htmlText":"Quick Start"},{"level":2,"text":"Client","anchor":"client","htmlText":"Client"},{"level":3,"text":"get_key()","anchor":"get_key","htmlText":"get_key()"},{"level":3,"text":"attest()","anchor":"attest","htmlText":"attest()"},{"level":3,"text":"attest_gpu()","anchor":"attest_gpu","htmlText":"attest_gpu()"},{"level":3,"text":"issue_cert()","anchor":"issue_cert","htmlText":"issue_cert()"},{"level":3,"text":"info()","anchor":"info","htmlText":"info()"},{"level":3,"text":"version()","anchor":"version","htmlText":"version()"},{"level":3,"text":"Async","anchor":"async","htmlText":"Async"},{"level":3,"text":"Signing and verifying","anchor":"signing-and-verifying","htmlText":"Signing and verifying"},{"level":2,"text":"Deployment Utilities","anchor":"deployment-utilities","htmlText":"Deployment Utilities"},{"level":3,"text":"Encrypted Environment Variables","anchor":"encrypted-environment-variables","htmlText":"Encrypted Environment Variables"},{"level":3,"text":"Calculate Compose Hash","anchor":"calculate-compose-hash","htmlText":"Calculate Compose Hash"},{"level":2,"text":"Compatibility","anchor":"compatibility","htmlText":"Compatibility"},{"level":2,"text":"Development","anchor":"development","htmlText":"Development"},{"level":1,"text":"Legacy (v0, frozen)","anchor":"legacy-v0-frozen","htmlText":"Legacy (v0, frozen)"},{"level":2,"text":"V0 Client","anchor":"v0-client","htmlText":"V0 Client"},{"level":3,"text":"Derive Keys","anchor":"derive-keys","htmlText":"Derive Keys"},{"level":3,"text":"Generate Attestation Quotes","anchor":"generate-attestation-quotes","htmlText":"Generate Attestation Quotes"},{"level":3,"text":"Versioned Attestation","anchor":"versioned-attestation","htmlText":"Versioned Attestation"},{"level":3,"text":"Get Instance Info","anchor":"get-instance-info","htmlText":"Get Instance Info"},{"level":3,"text":"Generate TLS Certificates","anchor":"generate-tls-certificates","htmlText":"Generate TLS Certificates"},{"level":3,"text":"Sign and Verify","anchor":"sign-and-verify","htmlText":"Sign and Verify"},{"level":3,"text":"Diagnostics","anchor":"diagnostics","htmlText":"Diagnostics"},{"level":3,"text":"Async","anchor":"async-1","htmlText":"Async"},{"level":3,"text":"Removed in 0.6.0","anchor":"removed-in-060","htmlText":"Removed in 0.6.0"},{"level":2,"text":"Blockchain helpers","anchor":"blockchain-helpers","htmlText":"Blockchain helpers"},{"level":2,"text":"Migration from TappdClient","anchor":"migration-from-tappdclient","htmlText":"Migration from TappdClient"},{"level":2,"text":"Migration from v0 to v1","anchor":"migration-from-v0-to-v1","htmlText":"Migration from v0 to v1"},{"level":2,"text":"License","anchor":"license","htmlText":"License"}]},"issueTemplate":null,"discussionTemplate":null,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch1 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003edstack SDK for Python\u003c/h1\u003e\u003ca id=\"user-content-dstack-sdk-for-python\" class=\"anchor\" aria-label=\"Permalink: dstack SDK for Python\" href=\"#dstack-sdk-for-python\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAccess TEE features from your Python application running inside dstack. Derive deterministic keys, request attestations, and issue TLS certificates—all backed by hardware security.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eThe default client speaks v1\u003c/h2\u003e\u003ca id=\"user-content-the-default-client-speaks-v1\" class=\"anchor\" aria-label=\"Permalink: The default client speaks v1\" href=\"#the-default-client-speaks-v1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003edstack 0.6.0 split the guest agent API into two surfaces on one socket, and the\nagent picks between them by URL path alone. This SDK mirrors both, and nothing\nmore — neither client translates calls to the other.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eClient\u003c/th\u003e\n\u003cth\u003eSurface\u003c/th\u003e\n\u003cth\u003ePaths\u003c/th\u003e\n\u003cth\u003eWhat it is\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eDstackClient\u003c/code\u003e / \u003ccode\u003eAsyncDstackClient\u003c/code\u003e — same classes as \u003ccode\u003eDstackClientV1\u003c/code\u003e / \u003ccode\u003eAsyncDstackClientV1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003edstack.guest.v1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e/v1/GetKey\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cstrong\u003eThe default.\u003c/strong\u003e Where every new capability lands\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eDstackClientV0\u003c/code\u003e / \u003ccode\u003eAsyncDstackClientV0\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003ethe frozen v0.5.11 API\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e/GetKey\u003c/code\u003e, equivalently \u003ccode\u003e/v0/GetKey\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eLegacy. Frozen: no new method, no new field, ever\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eUse the unsuffixed name in new code. The \u003ccode\u003eV1\u003c/code\u003e names are the same classes, spelled\nout for code that wants the surface visible at a glance.\u003c/p\u003e\n\u003cdiv class=\"markdown-alert markdown-alert-warning\" dir=\"auto\"\u003e\u003cp class=\"markdown-alert-title\" dir=\"auto\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-alert mr-2\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"\u003e\u003c/path\u003e\u003c/svg\u003eWarning\u003c/p\u003e\u003cp dir=\"auto\"\u003e\u003cstrong\u003ev1 derives different key material than v0.\u003c/strong\u003e \u003ccode\u003eDstackClient.get_key('x', 'secp256k1')\u003c/code\u003e\nand \u003ccode\u003eDstackClientV0.get_key('x')\u003c/code\u003e return different private keys. The v1 KDF binds\nthe algorithm and its own context tag alongside the domain, which is the point of\nthe new derivation, not a defect: v0 ignored the algorithm, so one secret served\ntwo curves. There is no compatibility mode and no flag that brings the old bytes\nback. An application that has published or committed to material derived from a v0\nkey must migrate deliberately — derive the v1 key, re-establish whatever depends on\nthe old one under it, and only then cut over.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eCode that used the unsuffixed client for v0 calls fails \u003cstrong\u003eloudly\u003c/strong\u003e on upgrade\nrather than silently deriving different keys, because the v1 method signatures\ndiffer and \u003ccode\u003eget_key\u003c/code\u003e requires \u003ccode\u003ealgorithm\u003c/code\u003e explicitly. To stay on the frozen\nsurface, switch to \u003ccode\u003eDstackClientV0\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe v1 surface serves only what genuinely needs the TEE, so it has no \u003ccode\u003esign\u003c/code\u003e, no\n\u003ccode\u003everify\u003c/code\u003e, no \u003ccode\u003eemit_event\u003c/code\u003e, no \u003ccode\u003eget_quote\u003c/code\u003e and no \u003ccode\u003egpu_info\u003c/code\u003e. See\n\u003ca href=\"/Dstack-TEE/dstack/blob/next/docs/guest-api-v1.md\"\u003e\u003ccode\u003edocs/guest-api-v1.md\u003c/code\u003e\u003c/a\u003e for the normative spec, and\n\u003ca href=\"#legacy-v0-frozen\"\u003eLegacy (v0, frozen)\u003c/a\u003e for the surface those methods live on.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInstallation\u003c/h2\u003e\u003ca id=\"user-content-installation\" class=\"anchor\" aria-label=\"Permalink: Installation\" href=\"#installation\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pip install dstack-sdk\"\u003e\u003cpre\u003epip install dstack-sdk\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBlockchain helpers are optional extras, needed only for the v0-era chain\nadapters (\u003ca href=\"#blockchain-helpers\"\u003eBlockchain helpers\u003c/a\u003e):\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eExtra\u003c/th\u003e\n\u003cth\u003ePulls in\u003c/th\u003e\n\u003cth\u003eUse when\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edstack-sdk[ethereum]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eeth-account\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eYou sign Ethereum transactions\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edstack-sdk[solana]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esolders\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eYou sign Solana transactions\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edstack-sdk[all]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eboth\u003c/td\u003e\n\u003ctd\u003eYou need both\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eAliases \u003ccode\u003e[eth]\u003c/code\u003e and \u003ccode\u003e[sol]\u003c/code\u003e are accepted for convenience.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eQuick Start\u003c/h2\u003e\u003ca id=\"user-content-quick-start\" class=\"anchor\" aria-label=\"Permalink: Quick Start\" href=\"#quick-start\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"from dstack_sdk import DstackClient\n\nclient = DstackClient()\n\nkey = client.get_key('storage-encryption', 'secp256k1')   # algorithm is required\nattestation = client.attest(b'my-app-state')\ninfo = client.info()\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDstackClient\u003c/span\u003e\n\n\u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eDstackClient\u003c/span\u003e()\n\n\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'storage-encryption'\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e'secp256k1'\u003c/span\u003e)   \u003cspan class=\"pl-c\"\u003e# algorithm is required\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003eattestation\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eattest\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003eb'my-app-state'\u003c/span\u003e)\n\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003einfo\u003c/span\u003e()\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe client automatically connects to \u003ccode\u003e/var/run/dstack.sock\u003c/code\u003e. For local\ndevelopment with the simulator:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"client = DstackClient('http://localhost:8090')\n# or export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eDstackClient\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'http://localhost:8090'\u003c/span\u003e)\n\u003cspan class=\"pl-c\"\u003e# or export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eEvery v1 method requires a 0.6.0+ guest agent: older agents have no \u003ccode\u003e/v1\u003c/code\u003e mount\nand answer HTTP 404.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eClient\u003c/h2\u003e\u003ca id=\"user-content-client\" class=\"anchor\" aria-label=\"Permalink: Client\" href=\"#client\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eDstackClient\u003c/code\u003e speaks \u003ccode\u003edstack.guest.v1\u003c/code\u003e at \u003ccode\u003e/v1/\u0026lt;Method\u0026gt;\u003c/code\u003e. Six methods, and\ndeliberately no more — v1 serves only what genuinely needs the TEE. In the\nexamples below, \u003ccode\u003eclient = DstackClient()\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eget_key()\u003c/code\u003e\u003c/h3\u003e\u003ca id=\"user-content-get_key\" class=\"anchor\" aria-label=\"Permalink: get_key()\" href=\"#get_key\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eDerives deterministic keys bound to your application's identity (\u003ccode\u003eapp_id\u003c/code\u003e). The\nsame domain always produces the same key for your app, and different apps get\ndifferent keys for the same domain.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"key = client.get_key('storage-encryption', 'secp256k1')\nprint(key.key)             # 32 raw bytes\nprint(key.public_key)      # SEC1 compressed (33 B), or 32 B for ed25519\nprint(key.signature_chain) # two links: app root, then KMS root\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'storage-encryption'\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e'secp256k1'\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ekey\u003c/span\u003e)             \u003cspan class=\"pl-c\"\u003e# 32 raw bytes\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003epublic_key\u003c/span\u003e)      \u003cspan class=\"pl-c\"\u003e# SEC1 compressed (33 B), or 32 B for ed25519\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003esignature_chain\u003c/span\u003e) \u003cspan class=\"pl-c\"\u003e# two links: app root, then KMS root\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eEvery field the proto declares \u003ccode\u003ebytes\u003c/code\u003e is \u003ccode\u003ebytes\u003c/code\u003e here, hex only on the wire.\n\u003ccode\u003epublic_key\u003c/code\u003e in particular is what the v1 key claim commits to, and the claim is\nbuilt over raw bytes — passing a hex string would build it over 66 ASCII\ncharacters and produce a chain that silently never verifies.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eParameters:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003edomain\u003c/code\u003e: Any string. This replaces v0's \u003ccode\u003epath\u003c/code\u003e plus \u003ccode\u003epurpose\u003c/code\u003e; in v0 only \u003ccode\u003epath\u003c/code\u003e reached the KDF and \u003ccode\u003epurpose\u003c/code\u003e was merely echoed into the chain claim. Derivation is flat — two domains give unrelated keys, and \u003ccode\u003ea/b\u003c/code\u003e is not a child of \u003ccode\u003ea\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ealgorithm\u003c/code\u003e: Exactly \u003ccode\u003e'secp256k1'\u003c/code\u003e or \u003ccode\u003e'ed25519'\u003c/code\u003e. \u003cstrong\u003eRequired.\u003c/strong\u003e There is no default and no \u003ccode\u003ek256\u003c/code\u003e alias, because in v0 a typo silently produced a key of the wrong type under a name the caller thought meant something else. An empty value is rejected client-side.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eReturns:\u003c/strong\u003e \u003ccode\u003eGetKeyResponseV1\u003c/code\u003e with \u003ccode\u003ekey: bytes\u003c/code\u003e, \u003ccode\u003epublic_key: bytes\u003c/code\u003e and\n\u003ccode\u003esignature_chain: list[bytes]\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eattest()\u003c/code\u003e\u003c/h3\u003e\u003ca id=\"user-content-attest\" class=\"anchor\" aria-label=\"Permalink: attest()\" href=\"#attest\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe sole CVM attestation entry point in v1. The dstack attestation format\nalready carries the quote and the event log, so v0's TDX-only \u003ccode\u003eget_quote\u003c/code\u003e has\nnothing left to add.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ereport_data\u003c/code\u003e is bytes, never \u003ccode\u003estr\u003c/code\u003e. v0 accepted a \u003ccode\u003estr\u003c/code\u003e and UTF-8 encoded it,\nso \u003ccode\u003eattest(\"deadbeef\")\u003c/code\u003e committed to the eight ASCII characters rather than the\nfour bytes they spell, with no error to say so; v1 makes you write\n\u003ccode\u003evalue.encode()\u003c/code\u003e or \u003ccode\u003ebytes.fromhex(value)\u003c/code\u003e at the call site, where it is visible\nwhich one was meant. \u003ccode\u003eattest_gpu\u003c/code\u003e's nonce is bytes only for the same reason.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"result = client.attest(b'user:alice:nonce123')\nprint(result.attestation)   # bytes\n\nwith_gpu = client.attest(b'user:alice:nonce123', include_boottime_gpu_evidence=True)\nfor bundle in with_gpu.boottime_gpu_evidence:\n    print(bundle.vendor, bundle.format, bundle.evidence)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eattest\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003eb'user:alice:nonce123'\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eattestation\u003c/span\u003e)   \u003cspan class=\"pl-c\"\u003e# bytes\u003c/span\u003e\n\n\u003cspan class=\"pl-s1\"\u003ewith_gpu\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eattest\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003eb'user:alice:nonce123'\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einclude_boottime_gpu_evidence\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTrue\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003efor\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003ein\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ewith_gpu\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eboottime_gpu_evidence\u003c/span\u003e:\n    \u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003evendor\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eformat\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eevidence\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ereport_data\u003c/code\u003e is 1–64 bytes and is zero-padded on the right to 64.\n\u003ccode\u003eboottime_gpu_evidence\u003c/code\u003e is a list of \u003ccode\u003eGpuEvidenceBundleV1\u003c/code\u003e — the same model\n\u003ccode\u003eattest_gpu()\u003c/code\u003e returns, so one bundle parser serves both methods. It is empty\nunless the flag was set and the guest has boot-time output; there is no\nsentinel. Boot-time bundles carry \u003ccode\u003eformat='nvidia-nvattest-boottime-json-v1'\u003c/code\u003e,\nagainst \u003ccode\u003eattest_gpu()\u003c/code\u003e's \u003ccode\u003e'nvidia-nvattest-collect-evidence-json-v1'\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBoot-time evidence is \u003cem\u003enot\u003c/em\u003e bound to \u003ccode\u003ereport_data\u003c/code\u003e — nvattest ran at boot\nagainst its own nonce. Bind it by replaying the runtime event log and comparing\nsha256 of \u003ccode\u003ebundle.evidence\u003c/code\u003e against \u003ccode\u003eevidence_sha256\u003c/code\u003e in the measured\n\u003ccode\u003egpu-attestation\u003c/code\u003e event. \u003ccode\u003eevidence\u003c/code\u003e is the nvattest output byte for byte; do not\nparse and re-serialize before hashing, since key order and whitespace change the\ndigest.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eattest_gpu()\u003c/code\u003e\u003c/h3\u003e\u003ca id=\"user-content-attest_gpu\" class=\"anchor\" aria-label=\"Permalink: attest_gpu()\" href=\"#attest_gpu\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSamples the GPU \u003cem\u003enow\u003c/em\u003e, against a nonce you choose — which is what\n\u003ccode\u003eboottime_gpu_evidence\u003c/code\u003e cannot tell you, since that is a record written at boot.\nUse it after anything that may have reinitialised the GPU.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"result = client.attest_gpu(os.urandom(32))  # exactly 32 bytes\nfor bundle in result.bundles:\n    print(bundle.vendor, bundle.format, bundle.evidence)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eattest_gpu\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eos\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eurandom\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e32\u003c/span\u003e))  \u003cspan class=\"pl-c\"\u003e# exactly 32 bytes\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efor\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003ein\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ebundles\u003c/span\u003e:\n    \u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003evendor\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eformat\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ebundle\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eevidence\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSelect a verifier using each bundle's \u003ccode\u003evendor\u003c/code\u003e and \u003ccode\u003eformat\u003c/code\u003e, then check the\nsignature, certificate chain, measurements, and the nonce embedded in the\nevidence. \u003ccode\u003eevidence\u003c/code\u003e is opaque vendor-native bytes, hex-encoded on the wire — do\nnot assume UTF-8 or JSON. It does not by itself bind the GPU to this CVM; only\nTDISP/TEE-IO device binding closes that gap.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eissue_cert()\u003c/code\u003e\u003c/h3\u003e\u003ca id=\"user-content-issue_cert\" class=\"anchor\" aria-label=\"Permalink: issue_cert()\" href=\"#issue_cert\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003ev0 called this \u003ccode\u003eget_tls_key()\u003c/code\u003e, which named the by-product rather than the\nrequest. The private key is freshly generated per call and is \u003cem\u003enot\u003c/em\u003e derived from\nthe app identity: two calls with the same arguments return two unrelated keys.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"cert = client.issue_cert(\n    subject='api.example.com',\n    alt_names=['localhost'],\n    usage_ra_tls=True,       # Embed the attestation in the certificate\n    usage_server_auth=True,\n    usage_client_auth=False,\n    with_app_info=True,\n    not_before=1700000000,   # seconds since UNIX epoch\n    not_after=1800000000,\n)\nprint(cert.key)                 # PEM private key\nprint(cert.certificate_chain)   # PEM chain, leaf first\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003ecert\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eissue_cert\u003c/span\u003e(\n    \u003cspan class=\"pl-s1\"\u003esubject\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'api.example.com'\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003ealt_names\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e[\u003cspan class=\"pl-s\"\u003e'localhost'\u003c/span\u003e],\n    \u003cspan class=\"pl-s1\"\u003eusage_ra_tls\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTrue\u003c/span\u003e,       \u003cspan class=\"pl-c\"\u003e# Embed the attestation in the certificate\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003eusage_server_auth\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTrue\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003eusage_client_auth\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eFalse\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003ewith_app_info\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTrue\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1700000000\u003c/span\u003e,   \u003cspan class=\"pl-c\"\u003e# seconds since UNIX epoch\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1800000000\u003c/span\u003e,\n)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ecert\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ekey\u003c/span\u003e)                 \u003cspan class=\"pl-c\"\u003e# PEM private key\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ecert\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecertificate_chain\u003c/span\u003e)   \u003cspan class=\"pl-c\"\u003e# PEM chain, leaf first\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eReturns:\u003c/strong\u003e \u003ccode\u003eIssueCertResponseV1\u003c/code\u003e with a PEM \u003ccode\u003ekey\u003c/code\u003e and a leaf-first\n\u003ccode\u003ecertificate_chain\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003einfo()\u003c/code\u003e\u003c/h3\u003e\u003ca id=\"user-content-info\" class=\"anchor\" aria-label=\"Permalink: info()\" href=\"#info\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"info = client.info()\nprint(info.app_id, info.app_name, info.compose_hash)\nprint(info.instance_id, info.device_id)\nprint(info.os_image_hash, info.mr_aggregated)\nprint(info.app_compose, info.vm_config, info.key_provider_info)\nprint(info.cloud_vendor, info.cloud_product)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003einfo\u003c/span\u003e()\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eapp_id\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eapp_name\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecompose_hash\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003einstance_id\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003edevice_id\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eos_image_hash\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003emr_aggregated\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eapp_compose\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003evm_config\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ekey_provider_info\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecloud_vendor\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecloud_product\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIdentity and configuration — not attestation. Nothing here is evidence: it\narrives over a local socket with no quote behind it. That is why there is no\n\u003ccode\u003etcb_info\u003c/code\u003e and no \u003ccode\u003eapp_cert\u003c/code\u003e. The measurement registers and the event log belong\nto \u003ccode\u003eattest()\u003c/code\u003e, which returns them quote-backed. \u003ccode\u003ecompose_hash\u003c/code\u003e, \u003ccode\u003eos_image_hash\u003c/code\u003e\nand \u003ccode\u003emr_aggregated\u003c/code\u003e are here because they identify \u003cem\u003ewhich\u003c/em\u003e application and image\nthis is, and a relying party still confirms them against an attestation.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eapp_compose\u003c/code\u003e is the verbatim deployed document and \u003ccode\u003ecompose_hash\u003c/code\u003e is sha256\nover exactly those bytes — do not parse and re-serialize before hashing.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eapp_id\u003c/code\u003e, \u003ccode\u003einstance_id\u003c/code\u003e, \u003ccode\u003ecompose_hash\u003c/code\u003e, \u003ccode\u003edevice_id\u003c/code\u003e, \u003ccode\u003eos_image_hash\u003c/code\u003e and\n\u003ccode\u003emr_aggregated\u003c/code\u003e are \u003ccode\u003ebytes\u003c/code\u003e, matching the proto. Call \u003ccode\u003e.hex()\u003c/code\u003e to print one.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003eversion()\u003c/code\u003e\u003c/h3\u003e\u003ca id=\"user-content-version\" class=\"anchor\" aria-label=\"Permalink: version()\" href=\"#version\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"client.version()   # VersionResponseV1(version, rev)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eversion\u003c/span\u003e()   \u003cspan class=\"pl-c\"\u003e# VersionResponseV1(version, rev)\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAsync\u003c/h3\u003e\u003ca id=\"user-content-async\" class=\"anchor\" aria-label=\"Permalink: Async\" href=\"#async\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eAsyncDstackClient\u003c/code\u003e has the identical surface, with every method a coroutine:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import asyncio\nfrom dstack_sdk import AsyncDstackClient\n\nasync def main():\n    client = AsyncDstackClient()\n\n    info = await client.info()\n    key = await client.get_key('backup-signing', 'ed25519')\n\n    # Run requests concurrently\n    keys = await asyncio.gather(\n        client.get_key('user/alice', 'secp256k1'),\n        client.get_key('user/bob', 'secp256k1'),\n    )\n\nasyncio.run(main())\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003easyncio\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eAsyncDstackClient\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003easync\u003c/span\u003e \u003cspan class=\"pl-k\"\u003edef\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e():\n    \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eAsyncDstackClient\u003c/span\u003e()\n\n    \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003einfo\u003c/span\u003e()\n    \u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'backup-signing'\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e'ed25519'\u003c/span\u003e)\n\n    \u003cspan class=\"pl-c\"\u003e# Run requests concurrently\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003ekeys\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003easyncio\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003egather\u003c/span\u003e(\n        \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'user/alice'\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e'secp256k1'\u003c/span\u003e),\n        \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'user/bob'\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e'secp256k1'\u003c/span\u003e),\n    )\n\n\u003cspan class=\"pl-s1\"\u003easyncio\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003erun\u003c/span\u003e(\u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e())\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eAsyncDstackClient\u003c/code\u003e accepts the same constructor as \u003ccode\u003eDstackClient\u003c/code\u003e plus\n\u003ccode\u003euse_sync_http: bool = False\u003c/code\u003e for callers that need to issue sync HTTP from\nwithin an async context. The same holds for the v0 clients.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSigning and verifying\u003c/h3\u003e\u003ca id=\"user-content-signing-and-verifying\" class=\"anchor\" aria-label=\"Permalink: Signing and verifying\" href=\"#signing-and-verifying\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNeither is a v1 method. Signing happens wherever the key is, and \u003ccode\u003eget_key()\u003c/code\u003e\nalready hands you the key, so a round trip to the agent adds nothing; verifying\nneeds no key at all, and an agent's answer arrives over the socket unattested,\nso a relying party gains nothing over checking the signature itself with a\nstandard library.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"from cryptography.hazmat.primitives.asymmetric import ed25519\n\nkey = client.get_key('signing/messages', 'ed25519')\nsigning_key = ed25519.Ed25519PrivateKey.from_private_bytes(key.key)\nsignature = signing_key.sign(b'message to sign')\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ecryptography\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ehazmat\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eprimitives\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003easymmetric\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eed25519\u003c/span\u003e\n\n\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'signing/messages'\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e'ed25519'\u003c/span\u003e)\n\u003cspan class=\"pl-s1\"\u003esigning_key\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eed25519\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eEd25519PrivateKey\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003efrom_private_bytes\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ekey\u003c/span\u003e)\n\u003cspan class=\"pl-s1\"\u003esignature\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003esigning_key\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003esign\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003eb'message to sign'\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eTo verify a v1 signature chain, follow\n\u003ca href=\"/Dstack-TEE/dstack/blob/next/docs/guest-api-v1.md\"\u003e\u003ccode\u003edocs/guest-api-v1.md\u003c/code\u003e\u003c/a\u003e, which is the normative\nspec: it gives the claim encoding, the link order, and — the part that actually\nestablishes anything — the requirement that the KMS root public key come from\nsomewhere you already trust (the \u003ccode\u003eDstackKms\u003c/code\u003e contract's \u003ccode\u003ekmsInfo().k256Pubkey\u003c/code\u003e,\nor a value you pinned), never from the CVM being checked.\u003c/p\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDeployment Utilities\u003c/h2\u003e\u003ca id=\"user-content-deployment-utilities\" class=\"anchor\" aria-label=\"Permalink: Deployment Utilities\" href=\"#deployment-utilities\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThese utilities are for deployment scripts, not runtime SDK operations, and are\nthe same for either client.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eEncrypted Environment Variables\u003c/h3\u003e\u003ca id=\"user-content-encrypted-environment-variables\" class=\"anchor\" aria-label=\"Permalink: Encrypted Environment Variables\" href=\"#encrypted-environment-variables\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe KMS returns a fresh X25519 public key (with a secp256k1 signature) that you encrypt secrets against before submitting them with your deployment. Always verify the signer before trusting the key:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"from dstack_sdk import (\n    encrypt_env_vars,\n    verify_env_encrypt_public_key,\n    EnvVar,\n)\n\n# `public_key`, `signature_v1`, `timestamp` come from KMS /GetAppEnvEncryptPubKey.\nsigner = verify_env_encrypt_public_key(\n    public_key=public_key_bytes,\n    signature=signature_v1_bytes,\n    app_id=app_id_hex,\n    timestamp=timestamp,\n)\nif signer is None:\n    raise RuntimeError('invalid KMS env-encrypt public key')\n\n# Always compare the recovered signer against a known-good KMS signer\n# address, obtained out-of-band from the DstackKms contract or your\n# deployment configuration. Without this check, an attacker could sign\n# their own env-encrypt key and the verification above would still pass.\nEXPECTED_KMS_SIGNER = '0x...'  # replace with your known KMS signer address\nif signer != EXPECTED_KMS_SIGNER:\n    raise RuntimeError(\n        f'unexpected KMS signer: got {signer}, '\n        f'expected {EXPECTED_KMS_SIGNER}'\n    )\n\nenv_vars = [\n    EnvVar(key='DATABASE_URL', value='postgresql://...'),\n    EnvVar(key='API_KEY', value='secret'),\n]\nencrypted = await encrypt_env_vars(env_vars, public_key_hex)\n# encrypt_env_vars_sync(...) is also available for non-async callers.\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e (\n    \u003cspan class=\"pl-s1\"\u003eencrypt_env_vars\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003everify_env_encrypt_public_key\u003c/span\u003e,\n    \u003cspan class=\"pl-v\"\u003eEnvVar\u003c/span\u003e,\n)\n\n\u003cspan class=\"pl-c\"\u003e# `public_key`, `signature_v1`, `timestamp` come from KMS /GetAppEnvEncryptPubKey.\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003esigner\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003everify_env_encrypt_public_key\u003c/span\u003e(\n    \u003cspan class=\"pl-s1\"\u003epublic_key\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003epublic_key_bytes\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003esignature\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003esignature_v1_bytes\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003eapp_id\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eapp_id_hex\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003etimestamp\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003etimestamp\u003c/span\u003e,\n)\n\u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003esigner\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eis\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eNone\u003c/span\u003e:\n    \u003cspan class=\"pl-k\"\u003eraise\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eRuntimeError\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'invalid KMS env-encrypt public key'\u003c/span\u003e)\n\n\u003cspan class=\"pl-c\"\u003e# Always compare the recovered signer against a known-good KMS signer\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e# address, obtained out-of-band from the DstackKms contract or your\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e# deployment configuration. Without this check, an attacker could sign\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e# their own env-encrypt key and the verification above would still pass.\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003eEXPECTED_KMS_SIGNER\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e'0x...'\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e# replace with your known KMS signer address\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003esigner\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e!=\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eEXPECTED_KMS_SIGNER\u003c/span\u003e:\n    \u003cspan class=\"pl-k\"\u003eraise\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eRuntimeError\u003c/span\u003e(\n        \u003cspan class=\"pl-s\"\u003ef'unexpected KMS signer: got \u003cspan class=\"pl-s1\"\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003esigner\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/span\u003e, '\u003c/span\u003e\n        \u003cspan class=\"pl-s\"\u003ef'expected \u003cspan class=\"pl-s1\"\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eEXPECTED_KMS_SIGNER\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/span\u003e'\u003c/span\u003e\n    )\n\n\u003cspan class=\"pl-s1\"\u003eenv_vars\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e [\n    \u003cspan class=\"pl-en\"\u003eEnvVar\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'DATABASE_URL'\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003evalue\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'postgresql://...'\u003c/span\u003e),\n    \u003cspan class=\"pl-en\"\u003eEnvVar\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'API_KEY'\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003evalue\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'secret'\u003c/span\u003e),\n]\n\u003cspan class=\"pl-s1\"\u003eencrypted\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eencrypt_env_vars\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eenv_vars\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003epublic_key_hex\u003c/span\u003e)\n\u003cspan class=\"pl-c\"\u003e# encrypt_env_vars_sync(...) is also available for non-async callers.\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003everify_env_encrypt_public_key\u003c/code\u003e returns the recovered compressed secp256k1 signer (\u003ccode\u003e0x\u003c/code\u003e-prefixed hex) on success, or \u003ccode\u003eNone\u003c/code\u003e for any failure (bad length, expired/future timestamp, malformed \u003ccode\u003eapp_id\u003c/code\u003e, invalid signature). The default \u003ccode\u003emax_age_seconds\u003c/code\u003e is 300; pass a larger value if your deployment workflow legitimately holds the response longer.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003everify_env_encrypt_public_key_legacy\u003c/code\u003e remains available only for deployments that explicitly support older KMS builds without \u003ccode\u003esignature_v1\u003c/code\u003e. It does not provide timestamp replay protection and should not be used for new deployments.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCalculate Compose Hash\u003c/h3\u003e\u003ca id=\"user-content-calculate-compose-hash\" class=\"anchor\" aria-label=\"Permalink: Calculate Compose Hash\" href=\"#calculate-compose-hash\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"from dstack_sdk import get_compose_hash\n\nhash_value = get_compose_hash(app_compose_dict)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eget_compose_hash\u003c/span\u003e\n\n\u003cspan class=\"pl-s1\"\u003ehash_value\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eget_compose_hash\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eapp_compose_dict\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCompatibility\u003c/h2\u003e\u003ca id=\"user-content-compatibility\" class=\"anchor\" aria-label=\"Permalink: Compatibility\" href=\"#compatibility\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eFeature\u003c/th\u003e\n\u003cth\u003eRequired dstack OS\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eEvery \u003ccode\u003eDstackClient\u003c/code\u003e (v1) method\u003c/td\u003e\n\u003ctd\u003e0.6.0+ — older agents have no \u003ccode\u003e/v1\u003c/code\u003e mount and answer HTTP 404\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eV0 \u003ccode\u003eget_key\u003c/code\u003e, \u003ccode\u003eget_quote\u003c/code\u003e, \u003ccode\u003eget_tls_key\u003c/code\u003e (legacy fields), \u003ccode\u003einfo\u003c/code\u003e (legacy fields)\u003c/td\u003e\n\u003ctd\u003e0.3+\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eV0 \u003ccode\u003eattest\u003c/code\u003e, \u003ccode\u003esign\u003c/code\u003e, \u003ccode\u003everify\u003c/code\u003e, \u003ccode\u003eis_reachable\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e0.5.0+ (\u003ccode\u003esign\u003c/code\u003e requires a server build with the feature)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eV0 \u003ccode\u003eversion\u003c/code\u003e, \u003ccode\u003ealgorithm='ed25519'\u003c/code\u003e on \u003ccode\u003eget_key\u003c/code\u003e, \u003ccode\u003einfo.cloud_vendor\u003c/code\u003e / \u003ccode\u003ecloud_product\u003c/code\u003e, \u003ccode\u003enot_before\u003c/code\u003e / \u003ccode\u003enot_after\u003c/code\u003e / \u003ccode\u003ewith_app_info\u003c/code\u003e on \u003ccode\u003eget_tls_key\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e0.5.7+\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eV0 \u003ccode\u003eemit_event\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRemoved in 0.6.0: the agent always fails it\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003everify_env_encrypt_public_key\u003c/code\u003e (signature_v1 with timestamp)\u003c/td\u003e\n\u003ctd\u003eRequires KMS build that emits \u003ccode\u003esignature_v1\u003c/code\u003e; legacy variant remains available\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eV0 calls that require 0.5.7-only fields probe the \u003ccode\u003eVersion\u003c/code\u003e RPC first and raise a clear \u003ccode\u003eRuntimeError\u003c/code\u003e on older guest agents. The v1 client never probes: it requires a 0.6 agent outright.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDevelopment\u003c/h2\u003e\u003ca id=\"user-content-development\" class=\"anchor\" aria-label=\"Permalink: Development\" href=\"#development\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFor local development without TDX hardware, use the simulator:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"git clone https://github.com/Dstack-TEE/dstack.git\ncd dstack/sdk/simulator\n./build.sh\n./dstack-simulator\"\u003e\u003cpre\u003egit clone https://github.com/Dstack-TEE/dstack.git\n\u003cspan class=\"pl-c1\"\u003ecd\u003c/span\u003e dstack/sdk/simulator\n./build.sh\n./dstack-simulator\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThen set the endpoint:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eexport\u003c/span\u003e DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eInstall dev dependencies, then run the tests and the format/lint checks with PDM:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"cd sdk/python\npdm install --dev\npdm run test\npdm run check\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003ecd\u003c/span\u003e sdk/python\npdm install --dev\npdm run \u003cspan class=\"pl-c1\"\u003etest\u003c/span\u003e\npdm run check\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003emake install\u003c/code\u003e / \u003ccode\u003emake test\u003c/code\u003e wrap the same commands and additionally assert that\n\u003ccode\u003eDSTACK_SIMULATOR_ENDPOINT\u003c/code\u003e and \u003ccode\u003eTAPPD_SIMULATOR_ENDPOINT\u003c/code\u003e are set.\u003c/p\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch1 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLegacy (v0, frozen)\u003c/h1\u003e\u003ca id=\"user-content-legacy-v0-frozen\" class=\"anchor\" aria-label=\"Permalink: Legacy (v0, frozen)\" href=\"#legacy-v0-frozen\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eEverything below is the frozen v0.5.11 surface. It still works and is still\nserved, but it gains no method and no field. Reach for it when you must keep the\nv0 key derivation, or when you need \u003ccode\u003esign\u003c/code\u003e / \u003ccode\u003everify\u003c/code\u003e, which v1 does not serve.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eImport it by its explicit name — the unsuffixed \u003ccode\u003eDstackClient\u003c/code\u003e now means v1:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"from dstack_sdk import DstackClientV0, AsyncDstackClientV0\n\nv0 = DstackClientV0()\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDstackClientV0\u003c/span\u003e, \u003cspan class=\"pl-v\"\u003eAsyncDstackClientV0\u003c/span\u003e\n\n\u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eDstackClientV0\u003c/span\u003e()\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eV0 Client\u003c/h2\u003e\u003ca id=\"user-content-v0-client\" class=\"anchor\" aria-label=\"Permalink: V0 Client\" href=\"#v0-client\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn the examples below, \u003ccode\u003ev0 = DstackClientV0()\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDerive Keys\u003c/h3\u003e\u003ca id=\"user-content-derive-keys\" class=\"anchor\" aria-label=\"Permalink: Derive Keys\" href=\"#derive-keys\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eget_key()\u003c/code\u003e derives deterministic keys bound to your application's identity (\u003ccode\u003eapp_id\u003c/code\u003e). The same path always produces the same key for your app, but different apps get different keys even with the same path.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# Derive keys by path\neth_key = v0.get_key('wallet/ethereum')\nbtc_key = v0.get_key('wallet/bitcoin')\n\n# Use path to separate keys\nmainnet_key = v0.get_key('wallet/eth/mainnet')\ntestnet_key = v0.get_key('wallet/eth/testnet')\n\n# Use a different signature algorithm (requires dstack OS \u0026gt;= 0.5.7)\ned_key = v0.get_key('signing/key', algorithm='ed25519')\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e# Derive keys by path\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003eeth_key\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'wallet/ethereum'\u003c/span\u003e)\n\u003cspan class=\"pl-s1\"\u003ebtc_key\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'wallet/bitcoin'\u003c/span\u003e)\n\n\u003cspan class=\"pl-c\"\u003e# Use path to separate keys\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003emainnet_key\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'wallet/eth/mainnet'\u003c/span\u003e)\n\u003cspan class=\"pl-s1\"\u003etestnet_key\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'wallet/eth/testnet'\u003c/span\u003e)\n\n\u003cspan class=\"pl-c\"\u003e# Use a different signature algorithm (requires dstack OS \u0026gt;= 0.5.7)\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003eed_key\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'signing/key'\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ealgorithm\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'ed25519'\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eParameters:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003epath\u003c/code\u003e (optional): Key derivation path. Defaults to \u003ccode\u003e\"\"\u003c/code\u003e (root).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003epurpose\u003c/code\u003e (optional): Included in the signature chain message; does not affect the derived key.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ealgorithm\u003c/code\u003e (optional): \u003ccode\u003e'secp256k1'\u003c/code\u003e (default) or \u003ccode\u003e'ed25519'\u003c/code\u003e. For compatibility, this selects how the same derived 32-byte material is interpreted; it does not domain-separate the derivation. Use algorithm-specific paths when independent keys are required.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eReturns:\u003c/strong\u003e \u003ccode\u003eGetKeyResponse\u003c/code\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ekey\u003c/code\u003e: Hex-encoded private key\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esignature_chain\u003c/code\u003e: Signatures proving the key was derived in a genuine TEE\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edecode_key()\u003c/code\u003e / \u003ccode\u003edecode_signature_chain()\u003c/code\u003e: Helpers that return \u003ccode\u003ebytes\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGenerate Attestation Quotes\u003c/h3\u003e\u003ca id=\"user-content-generate-attestation-quotes\" class=\"anchor\" aria-label=\"Permalink: Generate Attestation Quotes\" href=\"#generate-attestation-quotes\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eget_quote()\u003c/code\u003e creates a TDX quote proving your code runs in a genuine TEE.\nIt needs Intel TDX: without it the call fails, and on GCP Confidential VMs it\nreturns the TDX quote alone, leaving out the vTPM quote GCP's verification also\nbinds. Call \u003ccode\u003eattest()\u003c/code\u003e in both cases.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"quote = v0.get_quote(b'user:alice:nonce123')\nprint(quote.event_log)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003equote\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_quote\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003eb'user:alice:nonce123'\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003equote\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eevent_log\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eParameters:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ereport_data\u003c/code\u003e: Up to 64 bytes (\u003ccode\u003ebytes\u003c/code\u003e or \u003ccode\u003estr\u003c/code\u003e). Shorter inputs are padded with zeros; longer inputs should be hashed first (e.g., SHA-256).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eReturns:\u003c/strong\u003e \u003ccode\u003eGetQuoteResponse\u003c/code\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003equote\u003c/code\u003e: Hex-encoded TDX quote\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eevent_log\u003c/code\u003e: JSON string of measured events\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edecode_quote()\u003c/code\u003e / \u003ccode\u003edecode_event_log()\u003c/code\u003e: Helpers\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eVersioned Attestation\u003c/h3\u003e\u003ca id=\"user-content-versioned-attestation\" class=\"anchor\" aria-label=\"Permalink: Versioned Attestation\" href=\"#versioned-attestation\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eattest()\u003c/code\u003e returns a versioned attestation payload that newer verifier APIs can dispatch on without sniffing the quote format.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"result = v0.attest(b'user:alice:nonce123')\nprint(result.attestation)        # hex string\nprint(result.decode_attestation())  # bytes\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eattest\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003eb'user:alice:nonce123'\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eattestation\u003c/span\u003e)        \u003cspan class=\"pl-c\"\u003e# hex string\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003edecode_attestation\u003c/span\u003e())  \u003cspan class=\"pl-c\"\u003e# bytes\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ereport_data\u003c/code\u003e is the only argument. GPU evidence — boot-time and on-demand alike —\nis a v1 capability; see \u003ca href=\"#attest\"\u003e\u003ccode\u003eattest()\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"#attest_gpu\"\u003e\u003ccode\u003eattest_gpu()\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGet Instance Info\u003c/h3\u003e\u003ca id=\"user-content-get-instance-info\" class=\"anchor\" aria-label=\"Permalink: Get Instance Info\" href=\"#get-instance-info\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"info = v0.info()\nprint(info.app_id)\nprint(info.instance_id)\nprint(info.tcb_info)\nprint(info.cloud_vendor, info.cloud_product)  # 0.5.7+\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003einfo\u003c/span\u003e()\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eapp_id\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003einstance_id\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003etcb_info\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecloud_vendor\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecloud_product\u003c/span\u003e)  \u003cspan class=\"pl-c\"\u003e# 0.5.7+\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eReturns:\u003c/strong\u003e \u003ccode\u003eInfoResponse\u003c/code\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eapp_id\u003c/code\u003e, \u003ccode\u003einstance_id\u003c/code\u003e, \u003ccode\u003eapp_name\u003c/code\u003e, \u003ccode\u003edevice_id\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etcb_info\u003c/code\u003e: TCB measurements (MRTD, RTMRs, event log, compose hash, ...)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecompose_hash\u003c/code\u003e: Hash of the app configuration\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eapp_cert\u003c/code\u003e: Application certificate (PEM)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ekey_provider_info\u003c/code\u003e: Key management configuration\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecloud_vendor\u003c/code\u003e / \u003ccode\u003ecloud_product\u003c/code\u003e: Cloud provider strings (empty on older OS)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGenerate TLS Certificates\u003c/h3\u003e\u003ca id=\"user-content-generate-tls-certificates\" class=\"anchor\" aria-label=\"Permalink: Generate TLS Certificates\" href=\"#generate-tls-certificates\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eget_tls_key()\u003c/code\u003e creates fresh TLS certificates. Unlike \u003ccode\u003eget_key()\u003c/code\u003e, each call generates a new random key.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"tls = v0.get_tls_key(\n    subject='api.example.com',\n    alt_names=['localhost'],\n    usage_ra_tls=True,    # Embed attestation in certificate\n    # 0.5.7+ options below:\n    not_before=1700000000,   # seconds since UNIX epoch\n    not_after=1800000000,\n    with_app_info=True,\n)\nprint(tls.key)                  # PEM private key\nprint(tls.certificate_chain)    # Certificate chain\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003etls\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_tls_key\u003c/span\u003e(\n    \u003cspan class=\"pl-s1\"\u003esubject\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'api.example.com'\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003ealt_names\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e[\u003cspan class=\"pl-s\"\u003e'localhost'\u003c/span\u003e],\n    \u003cspan class=\"pl-s1\"\u003eusage_ra_tls\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTrue\u003c/span\u003e,    \u003cspan class=\"pl-c\"\u003e# Embed attestation in certificate\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e# 0.5.7+ options below:\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1700000000\u003c/span\u003e,   \u003cspan class=\"pl-c\"\u003e# seconds since UNIX epoch\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1800000000\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003ewith_app_info\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTrue\u003c/span\u003e,\n)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003etls\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ekey\u003c/span\u003e)                  \u003cspan class=\"pl-c\"\u003e# PEM private key\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003etls\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecertificate_chain\u003c/span\u003e)    \u003cspan class=\"pl-c\"\u003e# Certificate chain\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eParameters:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003esubject\u003c/code\u003e (optional): Certificate Common Name (e.g., domain name)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ealt_names\u003c/code\u003e (optional): Subject Alternative Names\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eusage_ra_tls\u003c/code\u003e (optional): Embed TDX quote in a certificate extension (default \u003ccode\u003eFalse\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eusage_server_auth\u003c/code\u003e (optional): Enable for server authentication (default \u003ccode\u003eTrue\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eusage_client_auth\u003c/code\u003e (optional): Enable for client authentication (default \u003ccode\u003eFalse\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003enot_before\u003c/code\u003e / \u003ccode\u003enot_after\u003c/code\u003e (optional, kw-only): Validity window in seconds since UNIX epoch. Requires dstack OS \u0026gt;= 0.5.7.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ewith_app_info\u003c/code\u003e (optional, kw-only): Embed app identity into the certificate. Requires dstack OS \u0026gt;= 0.5.7.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eWhen any of the 0.5.7-only options is set, the SDK probes \u003ccode\u003eVersion\u003c/code\u003e first and raises \u003ccode\u003eRuntimeError\u003c/code\u003e on older guest agents that lack it.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eReturns:\u003c/strong\u003e \u003ccode\u003eGetTlsKeyResponse\u003c/code\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ekey\u003c/code\u003e: PEM-encoded private key\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecertificate_chain\u003c/code\u003e: List of PEM certificates\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eas_uint8array(max_length=None)\u003c/code\u003e: Returns the DER-encoded private key bytes (handy when feeding key material into low-level crypto libraries)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSign and Verify\u003c/h3\u003e\u003ca id=\"user-content-sign-and-verify\" class=\"anchor\" aria-label=\"Permalink: Sign and Verify\" href=\"#sign-and-verify\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBoth are frozen v0 RPCs and neither has a v1 counterpart.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"result = v0.sign('ed25519', b'message to sign')\n\nverdict = v0.verify(\n    'ed25519',\n    b'message to sign',\n    result.decode_signature(),\n    result.decode_public_key(),\n)\nassert verdict.valid is True\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003esign\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'ed25519'\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003eb'message to sign'\u003c/span\u003e)\n\n\u003cspan class=\"pl-s1\"\u003everdict\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003everify\u003c/span\u003e(\n    \u003cspan class=\"pl-s\"\u003e'ed25519'\u003c/span\u003e,\n    \u003cspan class=\"pl-s\"\u003eb'message to sign'\u003c/span\u003e,\n    \u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003edecode_signature\u003c/span\u003e(),\n    \u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003edecode_public_key\u003c/span\u003e(),\n)\n\u003cspan class=\"pl-k\"\u003eassert\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003everdict\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003evalid\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eis\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003eTrue\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e\u003ccode\u003esign()\u003c/code\u003e Parameters:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ealgorithm\u003c/code\u003e: \u003ccode\u003e'ed25519'\u003c/code\u003e, \u003ccode\u003e'secp256k1'\u003c/code\u003e (alias \u003ccode\u003e'k256'\u003c/code\u003e), or \u003ccode\u003e'secp256k1_prehashed'\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edata\u003c/code\u003e: Data to sign (\u003ccode\u003ebytes\u003c/code\u003e or \u003ccode\u003estr\u003c/code\u003e). For \u003ccode\u003esecp256k1_prehashed\u003c/code\u003e, must be a 32-byte digest.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e\u003ccode\u003esign()\u003c/code\u003e Returns:\u003c/strong\u003e \u003ccode\u003eSignResponse\u003c/code\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003esignature\u003c/code\u003e: Hex-encoded signature\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003epublic_key\u003c/code\u003e: Hex-encoded public key\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esignature_chain\u003c/code\u003e: Three signatures linking the signing key back to the KMS root\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e\u003ccode\u003everify()\u003c/code\u003e Returns:\u003c/strong\u003e \u003ccode\u003eVerifyResponse\u003c/code\u003e with a single \u003ccode\u003evalid: bool\u003c/code\u003e. It reports\nonly whether that one signature matches that one public key — it says nothing\nabout \u003cem\u003ewhose\u003c/em\u003e key it is, and it does not walk the signature chain.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eEarlier drafts of this SDK shipped local \u003ccode\u003everify_signature\u003c/code\u003e and\n\u003ccode\u003everify_signature_chain\u003c/code\u003e helpers. They are gone; verify locally per\n\u003ca href=\"/Dstack-TEE/dstack/blob/next/docs/guest-api-v1.md\"\u003e\u003ccode\u003edocs/guest-api-v1.md\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDiagnostics\u003c/h3\u003e\u003ca id=\"user-content-diagnostics\" class=\"anchor\" aria-label=\"Permalink: Diagnostics\" href=\"#diagnostics\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"v0.version()        # VersionResponse(version, rev) — raises on OS \u0026lt; 0.5.7\nv0.is_reachable()   # Quick connectivity probe; never raises\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eversion\u003c/span\u003e()        \u003cspan class=\"pl-c\"\u003e# VersionResponse(version, rev) — raises on OS \u0026lt; 0.5.7\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eis_reachable\u003c/span\u003e()   \u003cspan class=\"pl-c\"\u003e# Quick connectivity probe; never raises\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAsync\u003c/h3\u003e\u003ca id=\"user-content-async-1\" class=\"anchor\" aria-label=\"Permalink: Async\" href=\"#async-1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eAsyncDstackClientV0\u003c/code\u003e has the identical surface, with every method a coroutine:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import asyncio\nfrom dstack_sdk import AsyncDstackClientV0\n\nasync def main():\n    v0 = AsyncDstackClientV0()\n\n    info = await v0.info()\n    key = await v0.get_key('wallet/eth')\n\n    # Run requests concurrently\n    keys = await asyncio.gather(\n        v0.get_key('user/alice'),\n        v0.get_key('user/bob'),\n    )\n\nasyncio.run(main())\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003easyncio\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eAsyncDstackClientV0\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003easync\u003c/span\u003e \u003cspan class=\"pl-k\"\u003edef\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e():\n    \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eAsyncDstackClientV0\u003c/span\u003e()\n\n    \u003cspan class=\"pl-s1\"\u003einfo\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003einfo\u003c/span\u003e()\n    \u003cspan class=\"pl-s1\"\u003ekey\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'wallet/eth'\u003c/span\u003e)\n\n    \u003cspan class=\"pl-c\"\u003e# Run requests concurrently\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003ekeys\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003easyncio\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003egather\u003c/span\u003e(\n        \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'user/alice'\u003c/span\u003e),\n        \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'user/bob'\u003c/span\u003e),\n    )\n\n\u003cspan class=\"pl-s1\"\u003easyncio\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003erun\u003c/span\u003e(\u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e())\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRemoved in 0.6.0\u003c/h3\u003e\u003ca id=\"user-content-removed-in-060\" class=\"anchor\" aria-label=\"Permalink: Removed in 0.6.0\" href=\"#removed-in-060\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eemit_event()\u003c/code\u003e is still on the client, but the agent now fails every call:\nruntime RTMR3 events are system-owned and an app can no longer extend them. The\nmethod remains so that a caller written against 0.5.x gets the agent's own\nexplanation rather than a 404. \u003ccode\u003eattest_gpu()\u003c/code\u003e and \u003ccode\u003egpu_info()\u003c/code\u003e never shipped on\nthis surface and are not here; they live on the v1 client.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eBlockchain helpers\u003c/h2\u003e\u003ca id=\"user-content-blockchain-helpers\" class=\"anchor\" aria-label=\"Permalink: Blockchain helpers\" href=\"#blockchain-helpers\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe chain adapters are v0-era. \u003ccode\u003edstack_sdk.ethereum\u003c/code\u003e and \u003ccode\u003edstack_sdk.solana\u003c/code\u003e\ntake a v0 \u003ccode\u003eGetKeyResponse\u003c/code\u003e or \u003ccode\u003eGetTlsKeyResponse\u003c/code\u003e, and that is the only shape\nthey take: v1 has no chain-related surface. \u003ccode\u003eget_key()\u003c/code\u003e returns key material,\nand what an application builds out of those bytes is its own business.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"from dstack_sdk import DstackClientV0\nfrom dstack_sdk.ethereum import to_account_secure\nfrom dstack_sdk.solana import to_keypair_secure\n\nv0 = DstackClientV0()\n\naccount = to_account_secure(v0.get_key('wallet/ethereum'))\nprint(account.address)\n\nkeypair = to_keypair_secure(\n    v0.get_key('wallet/solana', purpose='mainnet', algorithm='ed25519')\n)\nprint(keypair.pubkey())\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDstackClientV0\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eethereum\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eto_account_secure\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003esolana\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eto_keypair_secure\u003c/span\u003e\n\n\u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eDstackClientV0\u003c/span\u003e()\n\n\u003cspan class=\"pl-s1\"\u003eaccount\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eto_account_secure\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'wallet/ethereum'\u003c/span\u003e))\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eaccount\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eaddress\u003c/span\u003e)\n\n\u003cspan class=\"pl-s1\"\u003ekeypair\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eto_keypair_secure\u003c/span\u003e(\n    \u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eget_key\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e'wallet/solana'\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003epurpose\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'mainnet'\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ealgorithm\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e'ed25519'\u003c/span\u003e)\n)\n\u003cspan class=\"pl-en\"\u003eprint\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ekeypair\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003epubkey\u003c/span\u003e())\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eto_account_secure\u003c/code\u003e / \u003ccode\u003eto_keypair_secure\u003c/code\u003e hash the full key material with\nSHA-256 before deriving. The legacy \u003ccode\u003eto_account()\u003c/code\u003e / \u003ccode\u003eto_keypair()\u003c/code\u003e use raw key\nbytes and are kept only for backward compatibility.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMigration from TappdClient\u003c/h2\u003e\u003ca id=\"user-content-migration-from-tappdclient\" class=\"anchor\" aria-label=\"Permalink: Migration from TappdClient\" href=\"#migration-from-tappdclient\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eTappdClient\u003c/code\u003e only ever spoke v0, so replace it with \u003ccode\u003eDstackClientV0\u003c/code\u003e —\nnot with the unsuffixed name, which is now v1 and derives different keys:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-python notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# Before\nfrom dstack_sdk import TappdClient\nclient = TappdClient()\n\n# After\nfrom dstack_sdk import DstackClientV0\nv0 = DstackClientV0()\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e# Before\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTappdClient\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003eclient\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eTappdClient\u003c/span\u003e()\n\n\u003cspan class=\"pl-c\"\u003e# After\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edstack_sdk\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimport\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDstackClientV0\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003ev0\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eDstackClientV0\u003c/span\u003e()\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eMethod changes:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ederive_key()\u003c/code\u003e → \u003ccode\u003eget_tls_key()\u003c/code\u003e for TLS certificates\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etdx_quote()\u003c/code\u003e → \u003ccode\u003eget_quote()\u003c/code\u003e (raw data only, no hash algorithms)\u003c/li\u003e\n\u003cli\u003eSocket path: \u003ccode\u003e/var/run/tappd.sock\u003c/code\u003e → \u003ccode\u003e/var/run/dstack.sock\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMigration from v0 to v1\u003c/h2\u003e\u003ca id=\"user-content-migration-from-v0-to-v1\" class=\"anchor\" aria-label=\"Permalink: Migration from v0 to v1\" href=\"#migration-from-v0-to-v1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003ev1 is a separate surface, not an upgrade path — read the key warning at the top\nbefore switching anything that holds state.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003ev0\u003c/th\u003e\n\u003cth\u003ev1\u003c/th\u003e\n\u003cth\u003eNote\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eget_tls_key()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eissue_cert()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRenamed; same behaviour\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eget_key(path, purpose)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eget_key(domain, algorithm)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eMerged into one KDF input; \u003ccode\u003ealgorithm\u003c/code\u003e is now required\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eget_quote()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eattest()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eThe TDX-only channel is subsumed\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003einfo().tcb_info\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e—\u003c/td\u003e\n\u003ctd\u003eMeasurements are typed fields; the rest belongs to \u003ccode\u003eattest()\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003einfo().app_cert\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e—\u003c/td\u003e\n\u003ctd\u003eA dashboard artifact; it proved nothing\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003esign()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e—\u003c/td\u003e\n\u003ctd\u003eSign locally with the key \u003ccode\u003eget_key()\u003c/code\u003e returns\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003everify()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e—\u003c/td\u003e\n\u003ctd\u003eVerify locally, per \u003ccode\u003edocs/guest-api-v1.md\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eemit_event()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e—\u003c/td\u003e\n\u003ctd\u003eRTMR3 is system-owned as of 0.6.0\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003egpu_info()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eattest()\u003c/code\u003e with \u003ccode\u003einclude_boottime_gpu_evidence=True\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eSame bytes, now on the attestation call, in \u003ccode\u003eattest_gpu()\u003c/code\u003e's bundle shape\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLicense\u003c/h2\u003e\u003ca id=\"user-content-license\" class=\"anchor\" aria-label=\"Permalink: License\" href=\"#license\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eApache License 2.0\u003c/p\u003e\n\u003c/article\u003e","richTextTruncated":false,"renderedFileInfo":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"dstack SDK for Python","fully_qualified_name":"dstack SDK for Python","kind":"section_1","ident_start":2,"ident_end":23,"extent_start":0,"extent_end":14856,"ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":23}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":371,"utf16_col":0}}},{"name":"The default client speaks v1","fully_qualified_name":"The default client speaks v1","kind":"section_2","ident_start":212,"ident_end":240,"extent_start":209,"extent_end":2255,"ident_utf16":{"start":{"line_number":4,"utf16_col":3},"end":{"line_number":4,"utf16_col":31}},"extent_utf16":{"start":{"line_number":4,"utf16_col":0},"end":{"line_number":38,"utf16_col":0}}},{"name":"Installation","fully_qualified_name":"Installation","kind":"section_2","ident_start":2258,"ident_end":2270,"extent_start":2255,"extent_end":2731,"ident_utf16":{"start":{"line_number":38,"utf16_col":3},"end":{"line_number":38,"utf16_col":15}},"extent_utf16":{"start":{"line_number":38,"utf16_col":0},"end":{"line_number":55,"utf16_col":0}}},{"name":"Quick Start","fully_qualified_name":"Quick Start","kind":"section_2","ident_start":2734,"ident_end":2745,"extent_start":2731,"extent_end":3300,"ident_utf16":{"start":{"line_number":55,"utf16_col":3},"end":{"line_number":55,"utf16_col":14}},"extent_utf16":{"start":{"line_number":55,"utf16_col":0},"end":{"line_number":78,"utf16_col":0}}},{"name":"Client","fully_qualified_name":"Client","kind":"section_2","ident_start":3303,"ident_end":3309,"extent_start":3300,"extent_end":11040,"ident_utf16":{"start":{"line_number":78,"utf16_col":3},"end":{"line_number":78,"utf16_col":9}},"extent_utf16":{"start":{"line_number":78,"utf16_col":0},"end":{"line_number":268,"utf16_col":0}}},{"name":"`get_key()`","fully_qualified_name":"`get_key()`","kind":"section_3","ident_start":3512,"ident_end":3523,"extent_start":3508,"extent_end":4899,"ident_utf16":{"start":{"line_number":84,"utf16_col":4},"end":{"line_number":84,"utf16_col":15}},"extent_utf16":{"start":{"line_number":84,"utf16_col":0},"end":{"line_number":109,"utf16_col":0}}},{"name":"`attest()`","fully_qualified_name":"`attest()`","kind":"section_3","ident_start":4903,"ident_end":4913,"extent_start":4899,"extent_end":6606,"ident_utf16":{"start":{"line_number":109,"utf16_col":4},"end":{"line_number":109,"utf16_col":14}},"extent_utf16":{"start":{"line_number":109,"utf16_col":0},"end":{"line_number":144,"utf16_col":0}}},{"name":"`attest_gpu()`","fully_qualified_name":"`attest_gpu()`","kind":"section_3","ident_start":6610,"ident_end":6624,"extent_start":6606,"extent_end":7358,"ident_utf16":{"start":{"line_number":144,"utf16_col":4},"end":{"line_number":144,"utf16_col":18}},"extent_utf16":{"start":{"line_number":144,"utf16_col":0},"end":{"line_number":162,"utf16_col":0}}},{"name":"`issue_cert()`","fully_qualified_name":"`issue_cert()`","kind":"section_3","ident_start":7362,"ident_end":7376,"extent_start":7358,"extent_end":8149,"ident_utf16":{"start":{"line_number":162,"utf16_col":4},"end":{"line_number":162,"utf16_col":18}},"extent_utf16":{"start":{"line_number":162,"utf16_col":0},"end":{"line_number":186,"utf16_col":0}}},{"name":"`info()`","fully_qualified_name":"`info()`","kind":"section_3","ident_start":8153,"ident_end":8161,"extent_start":8149,"extent_end":9222,"ident_utf16":{"start":{"line_number":186,"utf16_col":4},"end":{"line_number":186,"utf16_col":12}},"extent_utf16":{"start":{"line_number":186,"utf16_col":0},"end":{"line_number":210,"utf16_col":0}}},{"name":"`version()`","fully_qualified_name":"`version()`","kind":"section_3","ident_start":9226,"ident_end":9237,"extent_start":9222,"extent_end":9307,"ident_utf16":{"start":{"line_number":210,"utf16_col":4},"end":{"line_number":210,"utf16_col":15}},"extent_utf16":{"start":{"line_number":210,"utf16_col":0},"end":{"line_number":216,"utf16_col":0}}},{"name":"Async","fully_qualified_name":"Async","kind":"section_3","ident_start":9311,"ident_end":9316,"extent_start":9307,"extent_end":10014,"ident_utf16":{"start":{"line_number":216,"utf16_col":4},"end":{"line_number":216,"utf16_col":9}},"extent_utf16":{"start":{"line_number":216,"utf16_col":0},"end":{"line_number":243,"utf16_col":0}}},{"name":"Signing and verifying","fully_qualified_name":"Signing and verifying","kind":"section_3","ident_start":10018,"ident_end":10039,"extent_start":10014,"extent_end":11040,"ident_utf16":{"start":{"line_number":243,"utf16_col":4},"end":{"line_number":243,"utf16_col":25}},"extent_utf16":{"start":{"line_number":243,"utf16_col":0},"end":{"line_number":268,"utf16_col":0}}},{"name":"Deployment Utilities","fully_qualified_name":"Deployment Utilities","kind":"section_2","ident_start":11043,"ident_end":11063,"extent_start":11040,"extent_end":13324,"ident_utf16":{"start":{"line_number":268,"utf16_col":3},"end":{"line_number":268,"utf16_col":23}},"extent_utf16":{"start":{"line_number":268,"utf16_col":0},"end":{"line_number":327,"utf16_col":0}}},{"name":"Encrypted Environment Variables","fully_qualified_name":"Encrypted Environment Variables","kind":"section_3","ident_start":11178,"ident_end":11209,"extent_start":11174,"extent_end":13187,"ident_utf16":{"start":{"line_number":273,"utf16_col":4},"end":{"line_number":273,"utf16_col":35}},"extent_utf16":{"start":{"line_number":273,"utf16_col":0},"end":{"line_number":317,"utf16_col":0}}},{"name":"Calculate Compose Hash","fully_qualified_name":"Calculate Compose Hash","kind":"section_3","ident_start":13191,"ident_end":13213,"extent_start":13187,"extent_end":13324,"ident_utf16":{"start":{"line_number":317,"utf16_col":4},"end":{"line_number":317,"utf16_col":26}},"extent_utf16":{"start":{"line_number":317,"utf16_col":0},"end":{"line_number":327,"utf16_col":0}}},{"name":"Compatibility","fully_qualified_name":"Compatibility","kind":"section_2","ident_start":13327,"ident_end":13340,"extent_start":13324,"extent_end":14256,"ident_utf16":{"start":{"line_number":327,"utf16_col":3},"end":{"line_number":327,"utf16_col":16}},"extent_utf16":{"start":{"line_number":327,"utf16_col":0},"end":{"line_number":340,"utf16_col":0}}},{"name":"Development","fully_qualified_name":"Development","kind":"section_2","ident_start":14259,"ident_end":14270,"extent_start":14256,"extent_end":14856,"ident_utf16":{"start":{"line_number":340,"utf16_col":3},"end":{"line_number":340,"utf16_col":14}},"extent_utf16":{"start":{"line_number":340,"utf16_col":0},"end":{"line_number":371,"utf16_col":0}}},{"name":"Legacy (v0, frozen)","fully_qualified_name":"Legacy (v0, frozen)","kind":"section_1","ident_start":14858,"ident_end":14877,"extent_start":14856,"extent_end":24456,"ident_utf16":{"start":{"line_number":371,"utf16_col":2},"end":{"line_number":371,"utf16_col":21}},"extent_utf16":{"start":{"line_number":371,"utf16_col":0},"end":{"line_number":639,"utf16_col":0}}},{"name":"V0 Client","fully_qualified_name":"V0 Client","kind":"section_2","ident_start":15297,"ident_end":15306,"extent_start":15294,"extent_end":22026,"ident_utf16":{"start":{"line_number":385,"utf16_col":3},"end":{"line_number":385,"utf16_col":12}},"extent_utf16":{"start":{"line_number":385,"utf16_col":0},"end":{"line_number":572,"utf16_col":0}}},{"name":"Derive Keys","fully_qualified_name":"Derive Keys","kind":"section_3","ident_start":15361,"ident_end":15372,"extent_start":15357,"extent_end":16606,"ident_utf16":{"start":{"line_number":389,"utf16_col":4},"end":{"line_number":389,"utf16_col":15}},"extent_utf16":{"start":{"line_number":389,"utf16_col":0},"end":{"line_number":416,"utf16_col":0}}},{"name":"Generate Attestation Quotes","fully_qualified_name":"Generate Attestation Quotes","kind":"section_3","ident_start":16610,"ident_end":16637,"extent_start":16606,"extent_end":17318,"ident_utf16":{"start":{"line_number":416,"utf16_col":4},"end":{"line_number":416,"utf16_col":31}},"extent_utf16":{"start":{"line_number":416,"utf16_col":0},"end":{"line_number":436,"utf16_col":0}}},{"name":"Versioned Attestation","fully_qualified_name":"Versioned Attestation","kind":"section_3","ident_start":17322,"ident_end":17343,"extent_start":17318,"extent_end":17790,"ident_utf16":{"start":{"line_number":436,"utf16_col":4},"end":{"line_number":436,"utf16_col":25}},"extent_utf16":{"start":{"line_number":436,"utf16_col":0},"end":{"line_number":449,"utf16_col":0}}},{"name":"Get Instance Info","fully_qualified_name":"Get Instance Info","kind":"section_3","ident_start":17794,"ident_end":17811,"extent_start":17790,"extent_end":18342,"ident_utf16":{"start":{"line_number":449,"utf16_col":4},"end":{"line_number":449,"utf16_col":21}},"extent_utf16":{"start":{"line_number":449,"utf16_col":0},"end":{"line_number":467,"utf16_col":0}}},{"name":"Generate TLS Certificates","fully_qualified_name":"Generate TLS Certificates","kind":"section_3","ident_start":18346,"ident_end":18371,"extent_start":18342,"extent_end":19901,"ident_utf16":{"start":{"line_number":467,"utf16_col":4},"end":{"line_number":467,"utf16_col":29}},"extent_utf16":{"start":{"line_number":467,"utf16_col":0},"end":{"line_number":501,"utf16_col":0}}},{"name":"Sign and Verify","fully_qualified_name":"Sign and Verify","kind":"section_3","ident_start":19905,"ident_end":19920,"extent_start":19901,"extent_end":21021,"ident_utf16":{"start":{"line_number":501,"utf16_col":4},"end":{"line_number":501,"utf16_col":19}},"extent_utf16":{"start":{"line_number":501,"utf16_col":0},"end":{"line_number":534,"utf16_col":0}}},{"name":"Diagnostics","fully_qualified_name":"Diagnostics","kind":"section_3","ident_start":21025,"ident_end":21036,"extent_start":21021,"extent_end":21191,"ident_utf16":{"start":{"line_number":534,"utf16_col":4},"end":{"line_number":534,"utf16_col":15}},"extent_utf16":{"start":{"line_number":534,"utf16_col":0},"end":{"line_number":541,"utf16_col":0}}},{"name":"Async","fully_qualified_name":"Async","kind":"section_3","ident_start":21195,"ident_end":21200,"extent_start":21191,"extent_end":21634,"ident_utf16":{"start":{"line_number":541,"utf16_col":4},"end":{"line_number":541,"utf16_col":9}},"extent_utf16":{"start":{"line_number":541,"utf16_col":0},"end":{"line_number":564,"utf16_col":0}}},{"name":"Removed in 0.6.0","fully_qualified_name":"Removed in 0.6.0","kind":"section_3","ident_start":21638,"ident_end":21654,"extent_start":21634,"extent_end":22026,"ident_utf16":{"start":{"line_number":564,"utf16_col":4},"end":{"line_number":564,"utf16_col":20}},"extent_utf16":{"start":{"line_number":564,"utf16_col":0},"end":{"line_number":572,"utf16_col":0}}},{"name":"Blockchain helpers","fully_qualified_name":"Blockchain helpers","kind":"section_2","ident_start":22029,"ident_end":22047,"extent_start":22026,"extent_end":22946,"ident_utf16":{"start":{"line_number":572,"utf16_col":3},"end":{"line_number":572,"utf16_col":21}},"extent_utf16":{"start":{"line_number":572,"utf16_col":0},"end":{"line_number":599,"utf16_col":0}}},{"name":"Migration from TappdClient","fully_qualified_name":"Migration from TappdClient","kind":"section_2","ident_start":22949,"ident_end":22975,"extent_start":22946,"extent_end":23486,"ident_utf16":{"start":{"line_number":599,"utf16_col":3},"end":{"line_number":599,"utf16_col":29}},"extent_utf16":{"start":{"line_number":599,"utf16_col":0},"end":{"line_number":619,"utf16_col":0}}},{"name":"Migration from v0 to v1","fully_qualified_name":"Migration from v0 to v1","kind":"section_2","ident_start":23489,"ident_end":23512,"extent_start":23486,"extent_end":24425,"ident_utf16":{"start":{"line_number":619,"utf16_col":3},"end":{"line_number":619,"utf16_col":26}},"extent_utf16":{"start":{"line_number":619,"utf16_col":0},"end":{"line_number":636,"utf16_col":0}}},{"name":"License","fully_qualified_name":"License","kind":"section_2","ident_start":24428,"ident_end":24435,"extent_start":24425,"extent_end":24456,"ident_utf16":{"start":{"line_number":636,"utf16_col":3},"end":{"line_number":636,"utf16_col":10}},"extent_utf16":{"start":{"line_number":636,"utf16_col":0},"end":{"line_number":639,"utf16_col":0}}}]}},"codeViewLayoutRoute":{"repo":{"id":856700396,"defaultBranch":"next","name":"dstack","ownerLogin":"Dstack-TEE","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2024-09-13T03:25:07.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/187594727?v=4","public":true,"private":false,"isOrgOwned":true,"isArchived":false},"currentUser":null,"uploadToken":"x3GWBDsR1ai_AZhS0ibJXAOCzUeeFMSLP9MzEEKT8x-O4P__UKkKJ6wGjDVVg-DwOjUlYwtTwaOE9Mc7TVt8_Q","allShortcutsEnabled":false,"treeExpanded":true,"path":"sdk/python/README.md","symbolsExpanded":false,"refInfo":{"name":"next","listCacheKey":"v0:1791539436.0","canEdit":false,"currentOid":"182fa12bd763a1de4e5f01a16f5d35baf93e0bae"},"helpUrl":"https://docs.github.com","githubDevUrl":null},"codeViewFileTreeLayoutRoute":{"fileTree":{"sdk/python":{"items":[{"name":"src","path":"sdk/python/src","contentType":"directory"},{"name":"tests","path":"sdk/python/tests","contentType":"directory"},{"name":".gitignore","path":"sdk/python/.gitignore","contentType":"file"},{"name":"Makefile","path":"sdk/python/Makefile","contentType":"file"},{"name":"README.md","path":"sdk/python/README.md","contentType":"file"},{"name":"mypy.ini","path":"sdk/python/mypy.ini","contentType":"file"},{"name":"pdm.lock","path":"sdk/python/pdm.lock","contentType":"file"},{"name":"pyproject.toml","path":"sdk/python/pyproject.toml","contentType":"file"},{"name":"test_outputs.py","path":"sdk/python/test_outputs.py","contentType":"file"}],"totalCount":9},"sdk":{"items":[{"name":"compat","path":"sdk/compat","contentType":"directory"},{"name":"curl","path":"sdk/curl","contentType":"directory"},{"name":"go","path":"sdk/go","contentType":"directory"},{"name":"js","path":"sdk/js","contentType":"directory"},{"name":"python","path":"sdk/python","contentType":"directory"},{"name":"rust","path":"sdk/rust","contentType":"directory"},{"name":"simulator","path":"sdk/simulator","contentType":"directory"},{"name":"README.md","path":"sdk/README.md","contentType":"file"},{"name":"run-tests.sh","path":"sdk/run-tests.sh","contentType":"file"}],"totalCount":9},"":{"items":[{"name":".agent","path":".agent","contentType":"directory"},{"name":".claude","path":".claude","contentType":"directory"},{"name":".github","path":".github","contentType":"directory"},{"name":"LICENSES","path":"LICENSES","contentType":"directory"},{"name":"docs","path":"docs","contentType":"directory"},{"name":"dstack","path":"dstack","contentType":"directory"},{"name":"examples","path":"examples","contentType":"directory"},{"name":"os","path":"os","contentType":"directory"},{"name":"sdk","path":"sdk","contentType":"directory"},{"name":"test-suites","path":"test-suites","contentType":"directory"},{"name":"tools","path":"tools","contentType":"directory"},{"name":".cursorrules","path":".cursorrules","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".gitmodules","path":".gitmodules","contentType":"file"},{"name":".mailmap","path":".mailmap","contentType":"file"},{"name":"CHANGELOG.md","path":"CHANGELOG.md","contentType":"file"},{"name":"CLAUDE.md","path":"CLAUDE.md","contentType":"file"},{"name":"CODE_OF_CONDUCT.md","path":"CODE_OF_CONDUCT.md","contentType":"file"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"Makefile","path":"Makefile","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"REUSE.toml","path":"REUSE.toml","contentType":"file"},{"name":"SECURITY.md","path":"SECURITY.md","contentType":"file"},{"name":"cliff.toml","path":"cliff.toml","contentType":"file"},{"name":"dstack-logo.svg","path":"dstack-logo.svg","contentType":"file"},{"name":"dstack_Technical_Charter_Final_10-17-2025.pdf","path":"dstack_Technical_Charter_Final_10-17-2025.pdf","contentType":"file"},{"name":"prek.toml","path":"prek.toml","contentType":"file"},{"name":"rust-toolchain.toml","path":"rust-toolchain.toml","contentType":"file"}],"totalCount":29}},"fileTreeProcessingTime":97.337703,"foldersToFetch":[]},"codeViewBlobLayoutRoute":{"codeLineWrapEnabled":false,"refInfo":{"name":"next","listCacheKey":"v0:1791539436.0","canEdit":false,"refType":"branch","currentOid":"182fa12bd763a1de4e5f01a16f5d35baf93e0bae","canEditOnDefaultBranch":false,"fileExistsOnDefault":true},"path":"sdk/python/README.md","blob":{"copilotSWEAgentEnabled":false,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/Dstack-TEE/dstack/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"README.md","displayUrl":"https://github.com/Dstack-TEE/dstack/blob/next/sdk/python/README.md?raw=true","headerInfo":{"blobSize":"23.9 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"9a67b3d","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2FDstack-TEE%2Fdstack%2Fblob%2Fnext%2Fsdk%2Fpython%2FREADME.md","isCSV":false,"isRichtext":true,"lineInfo":{"truncatedLoc":"639","truncatedSloc":"482"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"isIssueTemplate":false,"isDiscussionTemplate":false,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/Dstack-TEE/dstack/blob/next/sdk/python/README.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/Dstack-TEE/dstack/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/Dstack-TEE/dstack/raw/refs/heads/next/sdk/python/README.md","renderImageOrRaw":false,"shortPath":null,"symbolsEnabled":true,"tabSize":4,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null},"copilotInfo":null,"copilotAccessAllowed":false,"copilotSpacesEnabled":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"isMarketplaceEnabled":true},"codeViewBlobLayoutRoute.StyledBlob":{"rawLines":["# dstack SDK for Python","","Access TEE features from your Python application running inside dstack. Derive deterministic keys, request attestations, and issue TLS certificates—all backed by hardware security.","","## The default client speaks v1","","dstack 0.6.0 split the guest agent API into two surfaces on one socket, and the","agent picks between them by URL path alone. This SDK mirrors both, and nothing","more — neither client translates calls to the other.","","| Client | Surface | Paths | What it is |","|---|---|---|---|","| `DstackClient` / `AsyncDstackClient` — same classes as `DstackClientV1` / `AsyncDstackClientV1` | `dstack.guest.v1` | `/v1/GetKey` | **The default.** Where every new capability lands |","| `DstackClientV0` / `AsyncDstackClientV0` | the frozen v0.5.11 API | `/GetKey`, equivalently `/v0/GetKey` | Legacy. Frozen: no new method, no new field, ever |","","Use the unsuffixed name in new code. The `V1` names are the same classes, spelled","out for code that wants the surface visible at a glance.","","\u003e [!WARNING]","\u003e **v1 derives different key material than v0.** `DstackClient.get_key('x', 'secp256k1')`","\u003e and `DstackClientV0.get_key('x')` return different private keys. The v1 KDF binds","\u003e the algorithm and its own context tag alongside the domain, which is the point of","\u003e the new derivation, not a defect: v0 ignored the algorithm, so one secret served","\u003e two curves. There is no compatibility mode and no flag that brings the old bytes","\u003e back. An application that has published or committed to material derived from a v0","\u003e key must migrate deliberately — derive the v1 key, re-establish whatever depends on","\u003e the old one under it, and only then cut over.","\u003e","\u003e Code that used the unsuffixed client for v0 calls fails **loudly** on upgrade","\u003e rather than silently deriving different keys, because the v1 method signatures","\u003e differ and `get_key` requires `algorithm` explicitly. To stay on the frozen","\u003e surface, switch to `DstackClientV0`.","","The v1 surface serves only what genuinely needs the TEE, so it has no `sign`, no","`verify`, no `emit_event`, no `get_quote` and no `gpu_info`. See","[`docs/guest-api-v1.md`](../../docs/guest-api-v1.md) for the normative spec, and","[Legacy (v0, frozen)](#legacy-v0-frozen) for the surface those methods live on.","","## Installation","","```bash","pip install dstack-sdk","```","","Blockchain helpers are optional extras, needed only for the v0-era chain","adapters ([Blockchain helpers](#blockchain-helpers)):","","| Extra | Pulls in | Use when |","|---|---|---|","| `dstack-sdk[ethereum]` | `eth-account` | You sign Ethereum transactions |","| `dstack-sdk[solana]` | `solders` | You sign Solana transactions |","| `dstack-sdk[all]` | both | You need both |","","Aliases `[eth]` and `[sol]` are accepted for convenience.","","## Quick Start","","```python","from dstack_sdk import DstackClient","","client = DstackClient()","","key = client.get_key('storage-encryption', 'secp256k1')   # algorithm is required","attestation = client.attest(b'my-app-state')","info = client.info()","```","","The client automatically connects to `/var/run/dstack.sock`. For local","development with the simulator:","","```python","client = DstackClient('http://localhost:8090')","# or export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090","```","","Every v1 method requires a 0.6.0+ guest agent: older agents have no `/v1` mount","and answer HTTP 404.","","## Client","","`DstackClient` speaks `dstack.guest.v1` at `/v1/\u003cMethod\u003e`. Six methods, and","deliberately no more — v1 serves only what genuinely needs the TEE. In the","examples below, `client = DstackClient()`.","","### `get_key()`","","Derives deterministic keys bound to your application's identity (`app_id`). The","same domain always produces the same key for your app, and different apps get","different keys for the same domain.","","```python","key = client.get_key('storage-encryption', 'secp256k1')","print(key.key)             # 32 raw bytes","print(key.public_key)      # SEC1 compressed (33 B), or 32 B for ed25519","print(key.signature_chain) # two links: app root, then KMS root","```","","Every field the proto declares `bytes` is `bytes` here, hex only on the wire.","`public_key` in particular is what the v1 key claim commits to, and the claim is","built over raw bytes — passing a hex string would build it over 66 ASCII","characters and produce a chain that silently never verifies.","","**Parameters:**","- `domain`: Any string. This replaces v0's `path` plus `purpose`; in v0 only `path` reached the KDF and `purpose` was merely echoed into the chain claim. Derivation is flat — two domains give unrelated keys, and `a/b` is not a child of `a`.","- `algorithm`: Exactly `'secp256k1'` or `'ed25519'`. **Required.** There is no default and no `k256` alias, because in v0 a typo silently produced a key of the wrong type under a name the caller thought meant something else. An empty value is rejected client-side.","","**Returns:** `GetKeyResponseV1` with `key: bytes`, `public_key: bytes` and","`signature_chain: list[bytes]`.","","### `attest()`","","The sole CVM attestation entry point in v1. The dstack attestation format","already carries the quote and the event log, so v0's TDX-only `get_quote` has","nothing left to add.","","`report_data` is bytes, never `str`. v0 accepted a `str` and UTF-8 encoded it,","so `attest(\"deadbeef\")` committed to the eight ASCII characters rather than the","four bytes they spell, with no error to say so; v1 makes you write","`value.encode()` or `bytes.fromhex(value)` at the call site, where it is visible","which one was meant. `attest_gpu`'s nonce is bytes only for the same reason.","","```python","result = client.attest(b'user:alice:nonce123')","print(result.attestation)   # bytes","","with_gpu = client.attest(b'user:alice:nonce123', include_boottime_gpu_evidence=True)","for bundle in with_gpu.boottime_gpu_evidence:","    print(bundle.vendor, bundle.format, bundle.evidence)","```","","`report_data` is 1–64 bytes and is zero-padded on the right to 64.","`boottime_gpu_evidence` is a list of `GpuEvidenceBundleV1` — the same model","`attest_gpu()` returns, so one bundle parser serves both methods. It is empty","unless the flag was set and the guest has boot-time output; there is no","sentinel. Boot-time bundles carry `format='nvidia-nvattest-boottime-json-v1'`,","against `attest_gpu()`'s `'nvidia-nvattest-collect-evidence-json-v1'`.","","Boot-time evidence is *not* bound to `report_data` — nvattest ran at boot","against its own nonce. Bind it by replaying the runtime event log and comparing","sha256 of `bundle.evidence` against `evidence_sha256` in the measured","`gpu-attestation` event. `evidence` is the nvattest output byte for byte; do not","parse and re-serialize before hashing, since key order and whitespace change the","digest.","","### `attest_gpu()`","","Samples the GPU *now*, against a nonce you choose — which is what","`boottime_gpu_evidence` cannot tell you, since that is a record written at boot.","Use it after anything that may have reinitialised the GPU.","","```python","result = client.attest_gpu(os.urandom(32))  # exactly 32 bytes","for bundle in result.bundles:","    print(bundle.vendor, bundle.format, bundle.evidence)","```","","Select a verifier using each bundle's `vendor` and `format`, then check the","signature, certificate chain, measurements, and the nonce embedded in the","evidence. `evidence` is opaque vendor-native bytes, hex-encoded on the wire — do","not assume UTF-8 or JSON. It does not by itself bind the GPU to this CVM; only","TDISP/TEE-IO device binding closes that gap.","","### `issue_cert()`","","v0 called this `get_tls_key()`, which named the by-product rather than the","request. The private key is freshly generated per call and is *not* derived from","the app identity: two calls with the same arguments return two unrelated keys.","","```python","cert = client.issue_cert(","    subject='api.example.com',","    alt_names=['localhost'],","    usage_ra_tls=True,       # Embed the attestation in the certificate","    usage_server_auth=True,","    usage_client_auth=False,","    with_app_info=True,","    not_before=1700000000,   # seconds since UNIX epoch","    not_after=1800000000,",")","print(cert.key)                 # PEM private key","print(cert.certificate_chain)   # PEM chain, leaf first","```","","**Returns:** `IssueCertResponseV1` with a PEM `key` and a leaf-first","`certificate_chain`.","","### `info()`","","```python","info = client.info()","print(info.app_id, info.app_name, info.compose_hash)","print(info.instance_id, info.device_id)","print(info.os_image_hash, info.mr_aggregated)","print(info.app_compose, info.vm_config, info.key_provider_info)","print(info.cloud_vendor, info.cloud_product)","```","","Identity and configuration — not attestation. Nothing here is evidence: it","arrives over a local socket with no quote behind it. That is why there is no","`tcb_info` and no `app_cert`. The measurement registers and the event log belong","to `attest()`, which returns them quote-backed. `compose_hash`, `os_image_hash`","and `mr_aggregated` are here because they identify *which* application and image","this is, and a relying party still confirms them against an attestation.","","`app_compose` is the verbatim deployed document and `compose_hash` is sha256","over exactly those bytes — do not parse and re-serialize before hashing.","","`app_id`, `instance_id`, `compose_hash`, `device_id`, `os_image_hash` and","`mr_aggregated` are `bytes`, matching the proto. Call `.hex()` to print one.","","### `version()`","","```python","client.version()   # VersionResponseV1(version, rev)","```","","### Async","","`AsyncDstackClient` has the identical surface, with every method a coroutine:","","```python","import asyncio","from dstack_sdk import AsyncDstackClient","","async def main():","    client = AsyncDstackClient()","","    info = await client.info()","    key = await client.get_key('backup-signing', 'ed25519')","","    # Run requests concurrently","    keys = await asyncio.gather(","        client.get_key('user/alice', 'secp256k1'),","        client.get_key('user/bob', 'secp256k1'),","    )","","asyncio.run(main())","```","","`AsyncDstackClient` accepts the same constructor as `DstackClient` plus","`use_sync_http: bool = False` for callers that need to issue sync HTTP from","within an async context. The same holds for the v0 clients.","","### Signing and verifying","","Neither is a v1 method. Signing happens wherever the key is, and `get_key()`","already hands you the key, so a round trip to the agent adds nothing; verifying","needs no key at all, and an agent's answer arrives over the socket unattested,","so a relying party gains nothing over checking the signature itself with a","standard library.","","```python","from cryptography.hazmat.primitives.asymmetric import ed25519","","key = client.get_key('signing/messages', 'ed25519')","signing_key = ed25519.Ed25519PrivateKey.from_private_bytes(key.key)","signature = signing_key.sign(b'message to sign')","```","","To verify a v1 signature chain, follow","[`docs/guest-api-v1.md`](../../docs/guest-api-v1.md), which is the normative","spec: it gives the claim encoding, the link order, and — the part that actually","establishes anything — the requirement that the KMS root public key come from","somewhere you already trust (the `DstackKms` contract's `kmsInfo().k256Pubkey`,","or a value you pinned), never from the CVM being checked.","","---","","## Deployment Utilities","","These utilities are for deployment scripts, not runtime SDK operations, and are","the same for either client.","","### Encrypted Environment Variables","","The KMS returns a fresh X25519 public key (with a secp256k1 signature) that you encrypt secrets against before submitting them with your deployment. Always verify the signer before trusting the key:","","```python","from dstack_sdk import (","    encrypt_env_vars,","    verify_env_encrypt_public_key,","    EnvVar,",")","","# `public_key`, `signature_v1`, `timestamp` come from KMS /GetAppEnvEncryptPubKey.","signer = verify_env_encrypt_public_key(","    public_key=public_key_bytes,","    signature=signature_v1_bytes,","    app_id=app_id_hex,","    timestamp=timestamp,",")","if signer is None:","    raise RuntimeError('invalid KMS env-encrypt public key')","","# Always compare the recovered signer against a known-good KMS signer","# address, obtained out-of-band from the DstackKms contract or your","# deployment configuration. Without this check, an attacker could sign","# their own env-encrypt key and the verification above would still pass.","EXPECTED_KMS_SIGNER = '0x...'  # replace with your known KMS signer address","if signer != EXPECTED_KMS_SIGNER:","    raise RuntimeError(","        f'unexpected KMS signer: got {signer}, '","        f'expected {EXPECTED_KMS_SIGNER}'","    )","","env_vars = [","    EnvVar(key='DATABASE_URL', value='postgresql://...'),","    EnvVar(key='API_KEY', value='secret'),","]","encrypted = await encrypt_env_vars(env_vars, public_key_hex)","# encrypt_env_vars_sync(...) is also available for non-async callers.","```","","`verify_env_encrypt_public_key` returns the recovered compressed secp256k1 signer (`0x`-prefixed hex) on success, or `None` for any failure (bad length, expired/future timestamp, malformed `app_id`, invalid signature). The default `max_age_seconds` is 300; pass a larger value if your deployment workflow legitimately holds the response longer.","","`verify_env_encrypt_public_key_legacy` remains available only for deployments that explicitly support older KMS builds without `signature_v1`. It does not provide timestamp replay protection and should not be used for new deployments.","","### Calculate Compose Hash","","```python","from dstack_sdk import get_compose_hash","","hash_value = get_compose_hash(app_compose_dict)","```","","---","","## Compatibility","","| Feature | Required dstack OS |","|---|---|","| Every `DstackClient` (v1) method | 0.6.0+ — older agents have no `/v1` mount and answer HTTP 404 |","| V0 `get_key`, `get_quote`, `get_tls_key` (legacy fields), `info` (legacy fields) | 0.3+ |","| V0 `attest`, `sign`, `verify`, `is_reachable` | 0.5.0+ (`sign` requires a server build with the feature) |","| V0 `version`, `algorithm='ed25519'` on `get_key`, `info.cloud_vendor` / `cloud_product`, `not_before` / `not_after` / `with_app_info` on `get_tls_key` | 0.5.7+ |","| V0 `emit_event` | Removed in 0.6.0: the agent always fails it |","| `verify_env_encrypt_public_key` (signature_v1 with timestamp) | Requires KMS build that emits `signature_v1`; legacy variant remains available |","","V0 calls that require 0.5.7-only fields probe the `Version` RPC first and raise a clear `RuntimeError` on older guest agents. The v1 client never probes: it requires a 0.6 agent outright.","","## Development","","For local development without TDX hardware, use the simulator:","","```bash","git clone https://github.com/Dstack-TEE/dstack.git","cd dstack/sdk/simulator","./build.sh","./dstack-simulator","```","","Then set the endpoint:","","```bash","export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090","```","","Install dev dependencies, then run the tests and the format/lint checks with PDM:","","```bash","cd sdk/python","pdm install --dev","pdm run test","pdm run check","```","","`make install` / `make test` wrap the same commands and additionally assert that","`DSTACK_SIMULATOR_ENDPOINT` and `TAPPD_SIMULATOR_ENDPOINT` are set.","","---","","# Legacy (v0, frozen)","","Everything below is the frozen v0.5.11 surface. It still works and is still","served, but it gains no method and no field. Reach for it when you must keep the","v0 key derivation, or when you need `sign` / `verify`, which v1 does not serve.","","Import it by its explicit name — the unsuffixed `DstackClient` now means v1:","","```python","from dstack_sdk import DstackClientV0, AsyncDstackClientV0","","v0 = DstackClientV0()","```","","## V0 Client","","In the examples below, `v0 = DstackClientV0()`.","","### Derive Keys","","`get_key()` derives deterministic keys bound to your application's identity (`app_id`). The same path always produces the same key for your app, but different apps get different keys even with the same path.","","```python","# Derive keys by path","eth_key = v0.get_key('wallet/ethereum')","btc_key = v0.get_key('wallet/bitcoin')","","# Use path to separate keys","mainnet_key = v0.get_key('wallet/eth/mainnet')","testnet_key = v0.get_key('wallet/eth/testnet')","","# Use a different signature algorithm (requires dstack OS \u003e= 0.5.7)","ed_key = v0.get_key('signing/key', algorithm='ed25519')","```","","**Parameters:**","- `path` (optional): Key derivation path. Defaults to `\"\"` (root).","- `purpose` (optional): Included in the signature chain message; does not affect the derived key.","- `algorithm` (optional): `'secp256k1'` (default) or `'ed25519'`. For compatibility, this selects how the same derived 32-byte material is interpreted; it does not domain-separate the derivation. Use algorithm-specific paths when independent keys are required.","","**Returns:** `GetKeyResponse`","- `key`: Hex-encoded private key","- `signature_chain`: Signatures proving the key was derived in a genuine TEE","- `decode_key()` / `decode_signature_chain()`: Helpers that return `bytes`","","### Generate Attestation Quotes","","`get_quote()` creates a TDX quote proving your code runs in a genuine TEE.","It needs Intel TDX: without it the call fails, and on GCP Confidential VMs it","returns the TDX quote alone, leaving out the vTPM quote GCP's verification also","binds. Call `attest()` in both cases.","","```python","quote = v0.get_quote(b'user:alice:nonce123')","print(quote.event_log)","```","","**Parameters:**","- `report_data`: Up to 64 bytes (`bytes` or `str`). Shorter inputs are padded with zeros; longer inputs should be hashed first (e.g., SHA-256).","","**Returns:** `GetQuoteResponse`","- `quote`: Hex-encoded TDX quote","- `event_log`: JSON string of measured events","- `decode_quote()` / `decode_event_log()`: Helpers","","### Versioned Attestation","","`attest()` returns a versioned attestation payload that newer verifier APIs can dispatch on without sniffing the quote format.","","```python","result = v0.attest(b'user:alice:nonce123')","print(result.attestation)        # hex string","print(result.decode_attestation())  # bytes","```","","`report_data` is the only argument. GPU evidence — boot-time and on-demand alike —","is a v1 capability; see [`attest()`](#attest) and [`attest_gpu()`](#attest_gpu).","","### Get Instance Info","","```python","info = v0.info()","print(info.app_id)","print(info.instance_id)","print(info.tcb_info)","print(info.cloud_vendor, info.cloud_product)  # 0.5.7+","```","","**Returns:** `InfoResponse`","- `app_id`, `instance_id`, `app_name`, `device_id`","- `tcb_info`: TCB measurements (MRTD, RTMRs, event log, compose hash, ...)","- `compose_hash`: Hash of the app configuration","- `app_cert`: Application certificate (PEM)","- `key_provider_info`: Key management configuration","- `cloud_vendor` / `cloud_product`: Cloud provider strings (empty on older OS)","","### Generate TLS Certificates","","`get_tls_key()` creates fresh TLS certificates. Unlike `get_key()`, each call generates a new random key.","","```python","tls = v0.get_tls_key(","    subject='api.example.com',","    alt_names=['localhost'],","    usage_ra_tls=True,    # Embed attestation in certificate","    # 0.5.7+ options below:","    not_before=1700000000,   # seconds since UNIX epoch","    not_after=1800000000,","    with_app_info=True,",")","print(tls.key)                  # PEM private key","print(tls.certificate_chain)    # Certificate chain","```","","**Parameters:**","- `subject` (optional): Certificate Common Name (e.g., domain name)","- `alt_names` (optional): Subject Alternative Names","- `usage_ra_tls` (optional): Embed TDX quote in a certificate extension (default `False`)","- `usage_server_auth` (optional): Enable for server authentication (default `True`)","- `usage_client_auth` (optional): Enable for client authentication (default `False`)","- `not_before` / `not_after` (optional, kw-only): Validity window in seconds since UNIX epoch. Requires dstack OS \u003e= 0.5.7.","- `with_app_info` (optional, kw-only): Embed app identity into the certificate. Requires dstack OS \u003e= 0.5.7.","","When any of the 0.5.7-only options is set, the SDK probes `Version` first and raises `RuntimeError` on older guest agents that lack it.","","**Returns:** `GetTlsKeyResponse`","- `key`: PEM-encoded private key","- `certificate_chain`: List of PEM certificates","- `as_uint8array(max_length=None)`: Returns the DER-encoded private key bytes (handy when feeding key material into low-level crypto libraries)","","### Sign and Verify","","Both are frozen v0 RPCs and neither has a v1 counterpart.","","```python","result = v0.sign('ed25519', b'message to sign')","","verdict = v0.verify(","    'ed25519',","    b'message to sign',","    result.decode_signature(),","    result.decode_public_key(),",")","assert verdict.valid is True","```","","**`sign()` Parameters:**","- `algorithm`: `'ed25519'`, `'secp256k1'` (alias `'k256'`), or `'secp256k1_prehashed'`","- `data`: Data to sign (`bytes` or `str`). For `secp256k1_prehashed`, must be a 32-byte digest.","","**`sign()` Returns:** `SignResponse`","- `signature`: Hex-encoded signature","- `public_key`: Hex-encoded public key","- `signature_chain`: Three signatures linking the signing key back to the KMS root","","**`verify()` Returns:** `VerifyResponse` with a single `valid: bool`. It reports","only whether that one signature matches that one public key — it says nothing","about *whose* key it is, and it does not walk the signature chain.","","Earlier drafts of this SDK shipped local `verify_signature` and","`verify_signature_chain` helpers. They are gone; verify locally per","[`docs/guest-api-v1.md`](../../docs/guest-api-v1.md).","","### Diagnostics","","```python","v0.version()        # VersionResponse(version, rev) — raises on OS \u003c 0.5.7","v0.is_reachable()   # Quick connectivity probe; never raises","```","","### Async","","`AsyncDstackClientV0` has the identical surface, with every method a coroutine:","","```python","import asyncio","from dstack_sdk import AsyncDstackClientV0","","async def main():","    v0 = AsyncDstackClientV0()","","    info = await v0.info()","    key = await v0.get_key('wallet/eth')","","    # Run requests concurrently","    keys = await asyncio.gather(","        v0.get_key('user/alice'),","        v0.get_key('user/bob'),","    )","","asyncio.run(main())","```","","### Removed in 0.6.0","","`emit_event()` is still on the client, but the agent now fails every call:","runtime RTMR3 events are system-owned and an app can no longer extend them. The","method remains so that a caller written against 0.5.x gets the agent's own","explanation rather than a 404. `attest_gpu()` and `gpu_info()` never shipped on","this surface and are not here; they live on the v1 client.","","## Blockchain helpers","","The chain adapters are v0-era. `dstack_sdk.ethereum` and `dstack_sdk.solana`","take a v0 `GetKeyResponse` or `GetTlsKeyResponse`, and that is the only shape","they take: v1 has no chain-related surface. `get_key()` returns key material,","and what an application builds out of those bytes is its own business.","","```python","from dstack_sdk import DstackClientV0","from dstack_sdk.ethereum import to_account_secure","from dstack_sdk.solana import to_keypair_secure","","v0 = DstackClientV0()","","account = to_account_secure(v0.get_key('wallet/ethereum'))","print(account.address)","","keypair = to_keypair_secure(","    v0.get_key('wallet/solana', purpose='mainnet', algorithm='ed25519')",")","print(keypair.pubkey())","```","","`to_account_secure` / `to_keypair_secure` hash the full key material with","SHA-256 before deriving. The legacy `to_account()` / `to_keypair()` use raw key","bytes and are kept only for backward compatibility.","","## Migration from TappdClient","","`TappdClient` only ever spoke v0, so replace it with `DstackClientV0` —","not with the unsuffixed name, which is now v1 and derives different keys:","","```python","# Before","from dstack_sdk import TappdClient","client = TappdClient()","","# After","from dstack_sdk import DstackClientV0","v0 = DstackClientV0()","```","","Method changes:","- `derive_key()` → `get_tls_key()` for TLS certificates","- `tdx_quote()` → `get_quote()` (raw data only, no hash algorithms)","- Socket path: `/var/run/tappd.sock` → `/var/run/dstack.sock`","","## Migration from v0 to v1","","v1 is a separate surface, not an upgrade path — read the key warning at the top","before switching anything that holds state.","","| v0 | v1 | Note |","|---|---|---|","| `get_tls_key()` | `issue_cert()` | Renamed; same behaviour |","| `get_key(path, purpose)` | `get_key(domain, algorithm)` | Merged into one KDF input; `algorithm` is now required |","| `get_quote()` | `attest()` | The TDX-only channel is subsumed |","| `info().tcb_info` | — | Measurements are typed fields; the rest belongs to `attest()` |","| `info().app_cert` | — | A dashboard artifact; it proved nothing |","| `sign()` | — | Sign locally with the key `get_key()` returns |","| `verify()` | — | Verify locally, per `docs/guest-api-v1.md` |","| `emit_event()` | — | RTMR3 is system-owned as of 0.6.0 |","| `gpu_info()` | `attest()` with `include_boottime_gpu_evidence=True` | Same bytes, now on the attestation call, in `attest_gpu()`'s bundle shape |","","## License","","Apache License 2.0"],"stylingDirectives":[[[0,23,"pl-mh"],[2,23,"pl-en"]],[],[],[],[[0,31,"pl-mh"],[3,31,"pl-en"]],[],[],[],[],[],[[0,1,"pl-ml"],[9,10,"pl-ml"],[19,20,"pl-ml"],[27,28,"pl-ml"],[40,41,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"],[12,13,"pl-ml"],[16,17,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[19,20,"pl-s"],[20,37,"pl-c1"],[37,38,"pl-s"],[57,58,"pl-s"],[58,72,"pl-c1"],[72,73,"pl-s"],[76,77,"pl-s"],[77,96,"pl-c1"],[96,97,"pl-s"],[98,99,"pl-ml"],[100,101,"pl-s"],[101,116,"pl-c1"],[116,117,"pl-s"],[118,119,"pl-ml"],[120,121,"pl-s"],[121,131,"pl-c1"],[131,132,"pl-s"],[133,134,"pl-ml"],[135,137,"pl-s"],[149,151,"pl-s"],[185,186,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"],[21,22,"pl-s"],[22,41,"pl-c1"],[41,42,"pl-s"],[43,44,"pl-ml"],[68,69,"pl-ml"],[70,71,"pl-s"],[71,78,"pl-c1"],[78,79,"pl-s"],[94,95,"pl-s"],[95,105,"pl-c1"],[105,106,"pl-s"],[107,108,"pl-ml"],[159,160,"pl-ml"]],[],[[41,42,"pl-s"],[42,44,"pl-c1"],[44,45,"pl-s"]],[],[],[[0,12,"pl-ent"],[0,2,"pl-ent"],[2,3,"pl-s"],[11,12,"pl-s"]],[[0,89,"pl-ent"],[0,2,"pl-ent"],[2,4,"pl-s"],[46,48,"pl-s"],[49,50,"pl-s"],[50,88,"pl-c1"],[88,89,"pl-s"]],[[0,83,"pl-ent"],[0,2,"pl-ent"],[6,7,"pl-s"],[7,34,"pl-c1"],[34,35,"pl-s"]],[[0,83,"pl-ent"],[0,2,"pl-ent"]],[[0,82,"pl-ent"],[0,2,"pl-ent"]],[[0,82,"pl-ent"],[0,2,"pl-ent"]],[[0,84,"pl-ent"],[0,2,"pl-ent"]],[[0,85,"pl-ent"],[0,2,"pl-ent"]],[[0,47,"pl-ent"],[0,2,"pl-ent"]],[[0,1,"pl-ent"],[0,1,"pl-ent"]],[[0,79,"pl-ent"],[0,2,"pl-ent"],[58,60,"pl-s"],[66,68,"pl-s"]],[[0,80,"pl-ent"],[0,2,"pl-ent"]],[[0,77,"pl-ent"],[0,2,"pl-ent"],[13,14,"pl-s"],[14,21,"pl-c1"],[21,22,"pl-s"],[32,33,"pl-s"],[33,42,"pl-c1"],[42,43,"pl-s"]],[[0,38,"pl-ent"],[0,2,"pl-ent"],[21,22,"pl-s"],[22,36,"pl-c1"],[36,37,"pl-s"]],[[0,0,"pl-ent"]],[[70,71,"pl-s"],[71,75,"pl-c1"],[75,76,"pl-s"]],[[0,1,"pl-s"],[1,7,"pl-c1"],[7,8,"pl-s"],[13,14,"pl-s"],[14,24,"pl-c1"],[24,25,"pl-s"],[30,31,"pl-s"],[31,40,"pl-c1"],[40,41,"pl-s"],[49,50,"pl-s"],[50,58,"pl-c1"],[58,59,"pl-s"]],[[0,1,"pl-s"],[1,2,"pl-s"],[2,22,"pl-c1"],[22,23,"pl-s"],[23,24,"pl-s"],[24,25,"pl-s"],[25,51,"pl-corl"],[51,52,"pl-s"]],[[0,1,"pl-s"],[20,21,"pl-s"],[21,22,"pl-s"],[22,39,"pl-corl"],[39,40,"pl-s"]],[],[[0,15,"pl-mh"],[3,15,"pl-en"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[[10,11,"pl-s"],[29,30,"pl-s"],[30,31,"pl-s"],[31,50,"pl-corl"],[50,51,"pl-s"]],[],[[0,1,"pl-ml"],[8,9,"pl-ml"],[19,20,"pl-ml"],[30,31,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"],[12,13,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,23,"pl-c1"],[23,24,"pl-s"],[25,26,"pl-ml"],[27,28,"pl-s"],[28,39,"pl-c1"],[39,40,"pl-s"],[41,42,"pl-ml"],[74,75,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,21,"pl-c1"],[21,22,"pl-s"],[23,24,"pl-ml"],[25,26,"pl-s"],[26,33,"pl-c1"],[33,34,"pl-s"],[35,36,"pl-ml"],[66,67,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[20,21,"pl-ml"],[27,28,"pl-ml"],[43,44,"pl-ml"]],[],[[8,9,"pl-s"],[9,14,"pl-c1"],[14,15,"pl-s"],[20,21,"pl-s"],[21,26,"pl-c1"],[26,27,"pl-s"]],[],[[0,14,"pl-mh"],[3,14,"pl-en"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[],[[7,8,"pl-k"]],[],[[4,5,"pl-k"],[21,41,"pl-s"],[21,22,"pl-pds"],[40,41,"pl-pds"],[43,54,"pl-s"],[43,44,"pl-pds"],[53,54,"pl-pds"],[58,81,"pl-c"],[58,59,"pl-c"]],[[12,13,"pl-k"],[28,43,"pl-s"],[28,29,"pl-k"],[29,30,"pl-pds"],[42,43,"pl-pds"]],[[5,6,"pl-k"]],[[0,3,"pl-s"]],[],[[37,38,"pl-s"],[38,58,"pl-c1"],[58,59,"pl-s"]],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[7,8,"pl-k"],[22,45,"pl-s"],[22,23,"pl-pds"],[44,45,"pl-pds"]],[[0,59,"pl-c"],[0,1,"pl-c"]],[[0,3,"pl-s"]],[],[[68,69,"pl-s"],[69,72,"pl-c1"],[72,73,"pl-s"]],[],[],[[0,9,"pl-mh"],[3,9,"pl-en"]],[],[[0,1,"pl-s"],[1,13,"pl-c1"],[13,14,"pl-s"],[22,23,"pl-s"],[23,38,"pl-c1"],[38,39,"pl-s"],[43,44,"pl-s"],[44,56,"pl-c1"],[56,57,"pl-s"]],[],[[16,17,"pl-s"],[17,40,"pl-c1"],[40,41,"pl-s"]],[],[[0,15,"pl-mh"],[4,15,"pl-en"],[4,5,"pl-s"],[5,14,"pl-c1"],[14,15,"pl-s"]],[],[[65,66,"pl-s"],[66,72,"pl-c1"],[72,73,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[4,5,"pl-k"],[21,41,"pl-s"],[21,22,"pl-pds"],[40,41,"pl-pds"],[43,54,"pl-s"],[43,44,"pl-pds"],[53,54,"pl-pds"]],[[0,5,"pl-c1"],[27,41,"pl-c"],[27,28,"pl-c"]],[[0,5,"pl-c1"],[27,72,"pl-c"],[27,28,"pl-c"]],[[0,5,"pl-c1"],[27,63,"pl-c"],[27,28,"pl-c"]],[[0,3,"pl-s"]],[],[[31,32,"pl-s"],[32,37,"pl-c1"],[37,38,"pl-s"],[42,43,"pl-s"],[43,48,"pl-c1"],[48,49,"pl-s"]],[[0,1,"pl-s"],[1,11,"pl-c1"],[11,12,"pl-s"]],[],[],[],[[0,2,"pl-s"],[13,15,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,9,"pl-c1"],[9,10,"pl-s"],[43,44,"pl-s"],[44,48,"pl-c1"],[48,49,"pl-s"],[55,56,"pl-s"],[56,63,"pl-c1"],[63,64,"pl-s"],[77,78,"pl-s"],[78,82,"pl-c1"],[82,83,"pl-s"],[104,105,"pl-s"],[105,112,"pl-c1"],[112,113,"pl-s"],[212,213,"pl-s"],[213,216,"pl-c1"],[216,217,"pl-s"],[236,237,"pl-s"],[237,238,"pl-c1"],[238,239,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,12,"pl-c1"],[12,13,"pl-s"],[23,24,"pl-s"],[24,35,"pl-c1"],[35,36,"pl-s"],[40,41,"pl-s"],[41,50,"pl-c1"],[50,51,"pl-s"],[53,55,"pl-s"],[64,66,"pl-s"],[94,95,"pl-s"],[95,99,"pl-c1"],[99,100,"pl-s"]],[],[[0,2,"pl-s"],[10,12,"pl-s"],[13,14,"pl-s"],[14,30,"pl-c1"],[30,31,"pl-s"],[37,38,"pl-s"],[38,48,"pl-c1"],[48,49,"pl-s"],[51,52,"pl-s"],[52,69,"pl-c1"],[69,70,"pl-s"]],[[0,1,"pl-s"],[1,29,"pl-c1"],[29,30,"pl-s"]],[],[[0,14,"pl-mh"],[4,14,"pl-en"],[4,5,"pl-s"],[5,13,"pl-c1"],[13,14,"pl-s"]],[],[],[[62,63,"pl-s"],[63,72,"pl-c1"],[72,73,"pl-s"]],[],[],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"],[30,31,"pl-s"],[31,34,"pl-c1"],[34,35,"pl-s"],[51,52,"pl-s"],[52,55,"pl-c1"],[55,56,"pl-s"]],[[3,4,"pl-s"],[4,22,"pl-c1"],[22,23,"pl-s"]],[],[[0,1,"pl-s"],[1,15,"pl-c1"],[15,16,"pl-s"],[20,21,"pl-s"],[21,41,"pl-c1"],[41,42,"pl-s"]],[[21,22,"pl-s"],[22,32,"pl-c1"],[32,33,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[7,8,"pl-k"],[23,45,"pl-s"],[23,24,"pl-k"],[24,25,"pl-pds"],[44,45,"pl-pds"]],[[0,5,"pl-c1"],[28,35,"pl-c"],[28,29,"pl-c"]],[],[[9,10,"pl-k"],[25,47,"pl-s"],[25,26,"pl-k"],[26,27,"pl-pds"],[46,47,"pl-pds"],[49,78,"pl-v"],[78,79,"pl-k"],[79,83,"pl-c1"]],[[0,3,"pl-k"],[11,13,"pl-k"]],[[4,9,"pl-c1"]],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"]],[[0,1,"pl-s"],[1,22,"pl-c1"],[22,23,"pl-s"],[37,38,"pl-s"],[38,57,"pl-c1"],[57,58,"pl-s"]],[[0,1,"pl-s"],[1,13,"pl-c1"],[13,14,"pl-s"]],[],[[34,35,"pl-s"],[35,76,"pl-c1"],[76,77,"pl-s"]],[[8,9,"pl-s"],[9,21,"pl-c1"],[21,22,"pl-s"],[25,26,"pl-s"],[26,68,"pl-c1"],[68,69,"pl-s"]],[],[[22,23,"pl-s"],[26,27,"pl-s"],[37,38,"pl-s"],[38,49,"pl-c1"],[49,50,"pl-s"]],[],[[10,11,"pl-s"],[11,26,"pl-c1"],[26,27,"pl-s"],[36,37,"pl-s"],[37,52,"pl-c1"],[52,53,"pl-s"]],[[0,1,"pl-s"],[1,16,"pl-c1"],[16,17,"pl-s"],[25,26,"pl-s"],[26,34,"pl-c1"],[34,35,"pl-s"]],[],[],[],[[0,18,"pl-mh"],[4,18,"pl-en"],[4,5,"pl-s"],[5,17,"pl-c1"],[17,18,"pl-s"]],[],[[16,17,"pl-s"],[20,21,"pl-s"]],[[0,1,"pl-s"],[1,22,"pl-c1"],[22,23,"pl-s"]],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[7,8,"pl-k"],[38,40,"pl-c1"],[44,62,"pl-c"],[44,45,"pl-c"]],[[0,3,"pl-k"],[11,13,"pl-k"]],[[4,9,"pl-c1"]],[[0,3,"pl-s"]],[],[[38,39,"pl-s"],[39,45,"pl-c1"],[45,46,"pl-s"],[51,52,"pl-s"],[52,58,"pl-c1"],[58,59,"pl-s"]],[],[[10,11,"pl-s"],[11,19,"pl-c1"],[19,20,"pl-s"]],[],[],[],[[0,18,"pl-mh"],[4,18,"pl-en"],[4,5,"pl-s"],[5,17,"pl-c1"],[17,18,"pl-s"]],[],[[15,16,"pl-s"],[16,29,"pl-c1"],[29,30,"pl-s"]],[[62,63,"pl-s"],[66,67,"pl-s"]],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[5,6,"pl-k"]],[[4,11,"pl-v"],[11,12,"pl-k"],[12,29,"pl-s"],[12,13,"pl-pds"],[28,29,"pl-pds"]],[[4,13,"pl-v"],[13,14,"pl-k"],[15,26,"pl-s"],[15,16,"pl-pds"],[25,26,"pl-pds"]],[[4,16,"pl-v"],[16,17,"pl-k"],[17,21,"pl-c1"],[29,71,"pl-c"],[29,30,"pl-c"]],[[4,21,"pl-v"],[21,22,"pl-k"],[22,26,"pl-c1"]],[[4,21,"pl-v"],[21,22,"pl-k"],[22,27,"pl-c1"]],[[4,17,"pl-v"],[17,18,"pl-k"],[18,22,"pl-c1"]],[[4,14,"pl-v"],[14,15,"pl-k"],[15,25,"pl-c1"],[29,55,"pl-c"],[29,30,"pl-c"]],[[4,13,"pl-v"],[13,14,"pl-k"],[14,24,"pl-c1"]],[],[[0,5,"pl-c1"],[32,49,"pl-c"],[32,33,"pl-c"]],[[0,5,"pl-c1"],[32,55,"pl-c"],[32,33,"pl-c"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[10,12,"pl-s"],[13,14,"pl-s"],[14,33,"pl-c1"],[33,34,"pl-s"],[46,47,"pl-s"],[47,50,"pl-c1"],[50,51,"pl-s"]],[[0,1,"pl-s"],[1,18,"pl-c1"],[18,19,"pl-s"]],[],[[0,12,"pl-mh"],[4,12,"pl-en"],[4,5,"pl-s"],[5,11,"pl-c1"],[11,12,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[5,6,"pl-k"]],[[0,5,"pl-c1"]],[[0,5,"pl-c1"]],[[0,5,"pl-c1"]],[[0,5,"pl-c1"]],[[0,5,"pl-c1"]],[[0,3,"pl-s"]],[],[],[],[[0,1,"pl-s"],[1,9,"pl-c1"],[9,10,"pl-s"],[18,19,"pl-s"],[19,27,"pl-c1"],[27,28,"pl-s"]],[[3,4,"pl-s"],[4,12,"pl-c1"],[12,13,"pl-s"],[48,49,"pl-s"],[49,61,"pl-c1"],[61,62,"pl-s"],[64,65,"pl-s"],[65,78,"pl-c1"],[78,79,"pl-s"]],[[4,5,"pl-s"],[5,18,"pl-c1"],[18,19,"pl-s"],[51,52,"pl-s"],[57,58,"pl-s"]],[],[],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"],[52,53,"pl-s"],[53,65,"pl-c1"],[65,66,"pl-s"]],[],[],[[0,1,"pl-s"],[1,7,"pl-c1"],[7,8,"pl-s"],[10,11,"pl-s"],[11,22,"pl-c1"],[22,23,"pl-s"],[25,26,"pl-s"],[26,38,"pl-c1"],[38,39,"pl-s"],[41,42,"pl-s"],[42,51,"pl-c1"],[51,52,"pl-s"],[54,55,"pl-s"],[55,68,"pl-c1"],[68,69,"pl-s"]],[[0,1,"pl-s"],[1,14,"pl-c1"],[14,15,"pl-s"],[20,21,"pl-s"],[21,26,"pl-c1"],[26,27,"pl-s"],[54,55,"pl-s"],[55,61,"pl-c1"],[61,62,"pl-s"]],[],[[0,15,"pl-mh"],[4,15,"pl-en"],[4,5,"pl-s"],[5,14,"pl-c1"],[14,15,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[19,52,"pl-c"],[19,20,"pl-c"]],[[0,3,"pl-s"]],[],[[0,9,"pl-mh"],[4,9,"pl-en"]],[],[[0,1,"pl-s"],[1,18,"pl-c1"],[18,19,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,6,"pl-k"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[],[[0,5,"pl-k"],[6,9,"pl-k"],[10,14,"pl-en"]],[[11,12,"pl-k"]],[],[[9,10,"pl-k"],[11,16,"pl-k"]],[[8,9,"pl-k"],[10,15,"pl-k"],[31,47,"pl-s"],[31,32,"pl-pds"],[46,47,"pl-pds"],[49,58,"pl-s"],[49,50,"pl-pds"],[57,58,"pl-pds"]],[],[[4,31,"pl-c"],[4,5,"pl-c"]],[[9,10,"pl-k"],[11,16,"pl-k"]],[[23,35,"pl-s"],[23,24,"pl-pds"],[34,35,"pl-pds"],[37,48,"pl-s"],[37,38,"pl-pds"],[47,48,"pl-pds"]],[[23,33,"pl-s"],[23,24,"pl-pds"],[32,33,"pl-pds"],[35,46,"pl-s"],[35,36,"pl-pds"],[45,46,"pl-pds"]],[],[],[],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,18,"pl-c1"],[18,19,"pl-s"],[52,53,"pl-s"],[53,65,"pl-c1"],[65,66,"pl-s"]],[[0,1,"pl-s"],[1,28,"pl-c1"],[28,29,"pl-s"]],[],[],[[0,25,"pl-mh"],[4,25,"pl-en"]],[],[[65,66,"pl-s"],[66,75,"pl-c1"],[75,76,"pl-s"]],[],[],[],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,4,"pl-k"],[47,53,"pl-k"]],[],[[4,5,"pl-k"],[21,39,"pl-s"],[21,22,"pl-pds"],[38,39,"pl-pds"],[41,50,"pl-s"],[41,42,"pl-pds"],[49,50,"pl-pds"]],[[12,13,"pl-k"]],[[10,11,"pl-k"],[29,47,"pl-s"],[29,30,"pl-k"],[30,31,"pl-pds"],[46,47,"pl-pds"]],[[0,3,"pl-s"]],[],[],[[0,1,"pl-s"],[1,2,"pl-s"],[2,22,"pl-c1"],[22,23,"pl-s"],[23,24,"pl-s"],[24,25,"pl-s"],[25,51,"pl-corl"],[51,52,"pl-s"]],[],[],[[33,34,"pl-s"],[34,43,"pl-c1"],[43,44,"pl-s"],[56,57,"pl-s"],[57,77,"pl-c1"],[77,78,"pl-s"]],[],[],[[0,3,"pl-ms"]],[],[[0,23,"pl-mh"],[3,23,"pl-en"]],[],[],[],[],[[0,35,"pl-mh"],[4,35,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[],[],[],[],[],[[0,82,"pl-c"],[0,1,"pl-c"]],[[7,8,"pl-k"]],[[4,14,"pl-v"],[14,15,"pl-k"]],[[4,13,"pl-v"],[13,14,"pl-k"]],[[4,10,"pl-v"],[10,11,"pl-k"]],[[4,13,"pl-v"],[13,14,"pl-k"]],[],[[0,2,"pl-k"],[10,12,"pl-k"],[13,17,"pl-c1"]],[[4,9,"pl-k"],[10,22,"pl-c1"],[23,59,"pl-s"],[23,24,"pl-pds"],[58,59,"pl-pds"]],[],[[0,69,"pl-c"],[0,1,"pl-c"]],[[0,67,"pl-c"],[0,1,"pl-c"]],[[0,70,"pl-c"],[0,1,"pl-c"]],[[0,72,"pl-c"],[0,1,"pl-c"]],[[0,19,"pl-c1"],[20,21,"pl-k"],[22,29,"pl-s"],[22,23,"pl-pds"],[28,29,"pl-pds"],[31,75,"pl-c"],[31,32,"pl-c"]],[[0,2,"pl-k"],[10,12,"pl-k"],[13,32,"pl-c1"]],[[4,9,"pl-k"],[10,22,"pl-c1"]],[[8,9,"pl-s"],[9,10,"pl-pds"],[10,37,"pl-s"],[37,38,"pl-c1"],[44,45,"pl-c1"],[45,47,"pl-s"],[47,48,"pl-pds"]],[[8,9,"pl-s"],[9,10,"pl-pds"],[10,19,"pl-s"],[19,20,"pl-c1"],[20,39,"pl-c1"],[39,40,"pl-c1"],[40,41,"pl-pds"]],[],[],[[9,10,"pl-k"]],[[11,14,"pl-v"],[14,15,"pl-k"],[15,29,"pl-s"],[15,16,"pl-pds"],[28,29,"pl-pds"],[31,36,"pl-v"],[36,37,"pl-k"],[37,55,"pl-s"],[37,38,"pl-pds"],[54,55,"pl-pds"]],[[11,14,"pl-v"],[14,15,"pl-k"],[15,24,"pl-s"],[15,16,"pl-pds"],[23,24,"pl-pds"],[26,31,"pl-v"],[31,32,"pl-k"],[32,40,"pl-s"],[32,33,"pl-pds"],[39,40,"pl-pds"]],[],[[10,11,"pl-k"],[12,17,"pl-k"]],[[0,69,"pl-c"],[0,1,"pl-c"]],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,30,"pl-c1"],[30,31,"pl-s"],[83,84,"pl-s"],[84,86,"pl-c1"],[86,87,"pl-s"],[117,118,"pl-s"],[118,122,"pl-c1"],[122,123,"pl-s"],[189,190,"pl-s"],[190,196,"pl-c1"],[196,197,"pl-s"],[231,232,"pl-s"],[232,247,"pl-c1"],[247,248,"pl-s"]],[],[[0,1,"pl-s"],[1,37,"pl-c1"],[37,38,"pl-s"],[127,128,"pl-s"],[128,140,"pl-c1"],[140,141,"pl-s"]],[],[[0,26,"pl-mh"],[4,26,"pl-en"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[],[[11,12,"pl-k"]],[[0,3,"pl-s"]],[],[[0,3,"pl-ms"]],[],[[0,16,"pl-mh"],[3,16,"pl-en"]],[],[[0,1,"pl-ml"],[10,11,"pl-ml"],[31,32,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"]],[[0,1,"pl-ml"],[8,9,"pl-s"],[9,21,"pl-c1"],[21,22,"pl-s"],[35,36,"pl-ml"],[67,68,"pl-s"],[68,71,"pl-c1"],[71,72,"pl-s"],[99,100,"pl-ml"]],[[0,1,"pl-ml"],[5,6,"pl-s"],[6,13,"pl-c1"],[13,14,"pl-s"],[16,17,"pl-s"],[17,26,"pl-c1"],[26,27,"pl-s"],[29,30,"pl-s"],[30,41,"pl-c1"],[41,42,"pl-s"],[60,61,"pl-s"],[61,65,"pl-c1"],[65,66,"pl-s"],[83,84,"pl-ml"],[90,91,"pl-ml"]],[[0,1,"pl-ml"],[5,6,"pl-s"],[6,12,"pl-c1"],[12,13,"pl-s"],[15,16,"pl-s"],[16,20,"pl-c1"],[20,21,"pl-s"],[23,24,"pl-s"],[24,30,"pl-c1"],[30,31,"pl-s"],[33,34,"pl-s"],[34,46,"pl-c1"],[46,47,"pl-s"],[48,49,"pl-ml"],[58,59,"pl-s"],[59,63,"pl-c1"],[63,64,"pl-s"],[107,108,"pl-ml"]],[[0,1,"pl-ml"],[5,6,"pl-s"],[6,13,"pl-c1"],[13,14,"pl-s"],[16,17,"pl-s"],[17,36,"pl-c1"],[36,37,"pl-s"],[41,42,"pl-s"],[42,49,"pl-c1"],[49,50,"pl-s"],[52,53,"pl-s"],[53,70,"pl-c1"],[70,71,"pl-s"],[74,75,"pl-s"],[75,88,"pl-c1"],[88,89,"pl-s"],[91,92,"pl-s"],[92,102,"pl-c1"],[102,103,"pl-s"],[106,107,"pl-s"],[107,116,"pl-c1"],[116,117,"pl-s"],[120,121,"pl-s"],[121,134,"pl-c1"],[134,135,"pl-s"],[139,140,"pl-s"],[140,151,"pl-c1"],[151,152,"pl-s"],[153,154,"pl-ml"],[162,163,"pl-ml"]],[[0,1,"pl-ml"],[5,6,"pl-s"],[6,16,"pl-c1"],[16,17,"pl-s"],[18,19,"pl-ml"],[64,65,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,32,"pl-c1"],[32,33,"pl-s"],[64,65,"pl-ml"],[96,97,"pl-s"],[97,109,"pl-c1"],[109,110,"pl-s"],[145,146,"pl-ml"]],[],[[50,51,"pl-s"],[51,58,"pl-c1"],[58,59,"pl-s"],[88,89,"pl-s"],[89,101,"pl-c1"],[101,102,"pl-s"]],[],[[0,14,"pl-mh"],[3,14,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[],[[0,2,"pl-c1"]],[],[],[[0,3,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,6,"pl-k"]],[[0,3,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,2,"pl-c1"]],[],[[8,12,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,13,"pl-c1"],[13,14,"pl-s"],[17,18,"pl-s"],[18,27,"pl-c1"],[27,28,"pl-s"]],[[0,1,"pl-s"],[1,26,"pl-c1"],[26,27,"pl-s"],[32,33,"pl-s"],[33,57,"pl-c1"],[57,58,"pl-s"]],[],[[0,3,"pl-ms"]],[],[[0,21,"pl-mh"],[2,21,"pl-en"]],[],[],[],[[36,37,"pl-s"],[37,41,"pl-c1"],[41,42,"pl-s"],[45,46,"pl-s"],[46,52,"pl-c1"],[52,53,"pl-s"]],[],[[48,49,"pl-s"],[49,61,"pl-c1"],[61,62,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[],[[3,4,"pl-k"]],[[0,3,"pl-s"]],[],[[0,12,"pl-mh"],[3,12,"pl-en"]],[],[[23,24,"pl-s"],[24,45,"pl-c1"],[45,46,"pl-s"]],[],[[0,15,"pl-mh"],[4,15,"pl-en"]],[],[[0,1,"pl-s"],[1,10,"pl-c1"],[10,11,"pl-s"],[77,78,"pl-s"],[78,84,"pl-c1"],[84,85,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,21,"pl-c"],[0,1,"pl-c"]],[[8,9,"pl-k"],[21,38,"pl-s"],[21,22,"pl-pds"],[37,38,"pl-pds"]],[[8,9,"pl-k"],[21,37,"pl-s"],[21,22,"pl-pds"],[36,37,"pl-pds"]],[],[[0,27,"pl-c"],[0,1,"pl-c"]],[[12,13,"pl-k"],[25,45,"pl-s"],[25,26,"pl-pds"],[44,45,"pl-pds"]],[[12,13,"pl-k"],[25,45,"pl-s"],[25,26,"pl-pds"],[44,45,"pl-pds"]],[],[[0,67,"pl-c"],[0,1,"pl-c"]],[[7,8,"pl-k"],[20,33,"pl-s"],[20,21,"pl-pds"],[32,33,"pl-pds"],[35,44,"pl-v"],[44,45,"pl-k"],[45,54,"pl-s"],[45,46,"pl-pds"],[53,54,"pl-pds"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[13,15,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,7,"pl-c1"],[7,8,"pl-s"],[54,55,"pl-s"],[55,57,"pl-c1"],[57,58,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,10,"pl-c1"],[10,11,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,12,"pl-c1"],[12,13,"pl-s"],[26,27,"pl-s"],[27,38,"pl-c1"],[38,39,"pl-s"],[53,54,"pl-s"],[54,63,"pl-c1"],[63,64,"pl-s"]],[],[[0,2,"pl-s"],[10,12,"pl-s"],[13,14,"pl-s"],[14,28,"pl-c1"],[28,29,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,6,"pl-c1"],[6,7,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[19,20,"pl-s"],[20,44,"pl-c1"],[44,45,"pl-s"],[67,68,"pl-s"],[68,73,"pl-c1"],[73,74,"pl-s"]],[],[[0,31,"pl-mh"],[4,31,"pl-en"]],[],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"]],[],[],[[12,13,"pl-s"],[13,21,"pl-c1"],[21,22,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[6,7,"pl-k"],[21,43,"pl-s"],[21,22,"pl-k"],[22,23,"pl-pds"],[42,43,"pl-pds"]],[[0,5,"pl-c1"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[13,15,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"],[33,34,"pl-s"],[34,39,"pl-c1"],[39,40,"pl-s"],[44,45,"pl-s"],[45,48,"pl-c1"],[48,49,"pl-s"]],[],[[0,2,"pl-s"],[10,12,"pl-s"],[13,14,"pl-s"],[14,30,"pl-c1"],[30,31,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,8,"pl-c1"],[8,9,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,12,"pl-c1"],[12,13,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"],[21,22,"pl-s"],[22,40,"pl-c1"],[40,41,"pl-s"]],[],[[0,25,"pl-mh"],[4,25,"pl-en"]],[],[[0,1,"pl-s"],[1,9,"pl-c1"],[9,10,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[7,8,"pl-k"],[19,41,"pl-s"],[19,20,"pl-k"],[20,21,"pl-pds"],[40,41,"pl-pds"]],[[0,5,"pl-c1"],[33,45,"pl-c"],[33,34,"pl-c"]],[[0,5,"pl-c1"],[36,43,"pl-c"],[36,37,"pl-c"]],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"]],[[24,25,"pl-s"],[25,26,"pl-s"],[26,34,"pl-c1"],[34,35,"pl-s"],[35,36,"pl-s"],[36,37,"pl-s"],[37,44,"pl-corl"],[44,45,"pl-s"],[50,51,"pl-s"],[51,52,"pl-s"],[52,64,"pl-c1"],[64,65,"pl-s"],[65,66,"pl-s"],[66,67,"pl-s"],[67,78,"pl-corl"],[78,79,"pl-s"]],[],[[0,21,"pl-mh"],[4,21,"pl-en"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[5,6,"pl-k"]],[[0,5,"pl-c1"]],[[0,5,"pl-c1"]],[[0,5,"pl-c1"]],[[0,5,"pl-c1"],[46,54,"pl-c"],[46,47,"pl-c"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[10,12,"pl-s"],[13,14,"pl-s"],[14,26,"pl-c1"],[26,27,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,9,"pl-c1"],[9,10,"pl-s"],[12,13,"pl-s"],[13,24,"pl-c1"],[24,25,"pl-s"],[27,28,"pl-s"],[28,36,"pl-c1"],[36,37,"pl-s"],[39,40,"pl-s"],[40,49,"pl-c1"],[49,50,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,20,"pl-c1"],[20,21,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[19,20,"pl-s"],[20,33,"pl-c1"],[33,34,"pl-s"]],[],[[0,29,"pl-mh"],[4,29,"pl-en"]],[],[[0,1,"pl-s"],[1,14,"pl-c1"],[14,15,"pl-s"],[55,56,"pl-s"],[56,65,"pl-c1"],[65,66,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[4,5,"pl-k"]],[[4,11,"pl-v"],[11,12,"pl-k"],[12,29,"pl-s"],[12,13,"pl-pds"],[28,29,"pl-pds"]],[[4,13,"pl-v"],[13,14,"pl-k"],[15,26,"pl-s"],[15,16,"pl-pds"],[25,26,"pl-pds"]],[[4,16,"pl-v"],[16,17,"pl-k"],[17,21,"pl-c1"],[26,60,"pl-c"],[26,27,"pl-c"]],[[4,27,"pl-c"],[4,5,"pl-c"]],[[4,14,"pl-v"],[14,15,"pl-k"],[15,25,"pl-c1"],[29,55,"pl-c"],[29,30,"pl-c"]],[[4,13,"pl-v"],[13,14,"pl-k"],[14,24,"pl-c1"]],[[4,17,"pl-v"],[17,18,"pl-k"],[18,22,"pl-c1"]],[],[[0,5,"pl-c1"],[32,49,"pl-c"],[32,33,"pl-c"]],[[0,5,"pl-c1"],[32,51,"pl-c"],[32,33,"pl-c"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[13,15,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,10,"pl-c1"],[10,11,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,12,"pl-c1"],[12,13,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[81,82,"pl-s"],[82,87,"pl-c1"],[87,88,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,20,"pl-c1"],[20,21,"pl-s"],[76,77,"pl-s"],[77,81,"pl-c1"],[81,82,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,20,"pl-c1"],[20,21,"pl-s"],[76,77,"pl-s"],[77,82,"pl-c1"],[82,83,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"],[17,18,"pl-s"],[18,27,"pl-c1"],[27,28,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,16,"pl-c1"],[16,17,"pl-s"]],[],[[58,59,"pl-s"],[59,66,"pl-c1"],[66,67,"pl-s"],[85,86,"pl-s"],[86,98,"pl-c1"],[98,99,"pl-s"]],[],[[0,2,"pl-s"],[10,12,"pl-s"],[13,14,"pl-s"],[14,31,"pl-c1"],[31,32,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,6,"pl-c1"],[6,7,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,20,"pl-c1"],[20,21,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,33,"pl-c1"],[33,34,"pl-s"]],[],[[0,19,"pl-mh"],[4,19,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[7,8,"pl-k"],[17,26,"pl-s"],[17,18,"pl-pds"],[25,26,"pl-pds"],[28,46,"pl-s"],[28,29,"pl-k"],[29,30,"pl-pds"],[45,46,"pl-pds"]],[],[[8,9,"pl-k"]],[[4,13,"pl-s"],[4,5,"pl-pds"],[12,13,"pl-pds"]],[[4,22,"pl-s"],[4,5,"pl-k"],[5,6,"pl-pds"],[21,22,"pl-pds"]],[],[],[],[[0,6,"pl-k"],[21,23,"pl-k"],[24,28,"pl-c1"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[2,3,"pl-s"],[3,9,"pl-c1"],[9,10,"pl-s"],[22,24,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,12,"pl-c1"],[12,13,"pl-s"],[15,16,"pl-s"],[16,25,"pl-c1"],[25,26,"pl-s"],[28,29,"pl-s"],[29,40,"pl-c1"],[40,41,"pl-s"],[49,50,"pl-s"],[50,56,"pl-c1"],[56,57,"pl-s"],[63,64,"pl-s"],[64,85,"pl-c1"],[85,86,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,7,"pl-c1"],[7,8,"pl-s"],[24,25,"pl-s"],[25,30,"pl-c1"],[30,31,"pl-s"],[35,36,"pl-s"],[36,39,"pl-c1"],[39,40,"pl-s"],[47,48,"pl-s"],[48,67,"pl-c1"],[67,68,"pl-s"]],[],[[0,2,"pl-s"],[2,3,"pl-s"],[3,9,"pl-c1"],[9,10,"pl-s"],[19,21,"pl-s"],[22,23,"pl-s"],[23,35,"pl-c1"],[35,36,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,12,"pl-c1"],[12,13,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"]],[],[[0,2,"pl-s"],[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"],[21,23,"pl-s"],[24,25,"pl-s"],[25,39,"pl-c1"],[39,40,"pl-s"],[55,56,"pl-s"],[56,67,"pl-c1"],[67,68,"pl-s"]],[],[[6,7,"pl-s"],[12,13,"pl-s"]],[],[[41,42,"pl-s"],[42,58,"pl-c1"],[58,59,"pl-s"]],[[0,1,"pl-s"],[1,23,"pl-c1"],[23,24,"pl-s"]],[[0,1,"pl-s"],[1,2,"pl-s"],[2,22,"pl-c1"],[22,23,"pl-s"],[23,24,"pl-s"],[24,25,"pl-s"],[25,51,"pl-corl"],[51,52,"pl-s"]],[],[[0,15,"pl-mh"],[4,15,"pl-en"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[20,74,"pl-c"],[20,21,"pl-c"]],[[20,60,"pl-c"],[20,21,"pl-c"]],[[0,3,"pl-s"]],[],[[0,9,"pl-mh"],[4,9,"pl-en"]],[],[[0,1,"pl-s"],[1,20,"pl-c1"],[20,21,"pl-s"]],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,6,"pl-k"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[],[[0,5,"pl-k"],[6,9,"pl-k"],[10,14,"pl-en"]],[[7,8,"pl-k"]],[],[[9,10,"pl-k"],[11,16,"pl-k"]],[[8,9,"pl-k"],[10,15,"pl-k"],[27,39,"pl-s"],[27,28,"pl-pds"],[38,39,"pl-pds"]],[],[[4,31,"pl-c"],[4,5,"pl-c"]],[[9,10,"pl-k"],[11,16,"pl-k"]],[[19,31,"pl-s"],[19,20,"pl-pds"],[30,31,"pl-pds"]],[[19,29,"pl-s"],[19,20,"pl-pds"],[28,29,"pl-pds"]],[],[],[],[[0,3,"pl-s"]],[],[[0,20,"pl-mh"],[4,20,"pl-en"]],[],[[0,1,"pl-s"],[1,13,"pl-c1"],[13,14,"pl-s"]],[],[],[[31,32,"pl-s"],[32,44,"pl-c1"],[44,45,"pl-s"],[50,51,"pl-s"],[51,61,"pl-c1"],[61,62,"pl-s"]],[],[],[[0,21,"pl-mh"],[3,21,"pl-en"]],[],[[31,32,"pl-s"],[32,51,"pl-c1"],[51,52,"pl-s"],[57,58,"pl-s"],[58,75,"pl-c1"],[75,76,"pl-s"]],[[10,11,"pl-s"],[11,25,"pl-c1"],[25,26,"pl-s"],[30,31,"pl-s"],[31,48,"pl-c1"],[48,49,"pl-s"]],[[44,45,"pl-s"],[45,54,"pl-c1"],[54,55,"pl-s"]],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[[0,4,"pl-k"],[25,31,"pl-k"]],[[0,4,"pl-k"],[23,29,"pl-k"]],[],[[3,4,"pl-k"]],[],[[8,9,"pl-k"],[39,56,"pl-s"],[39,40,"pl-pds"],[55,56,"pl-pds"]],[[0,5,"pl-c1"]],[],[[8,9,"pl-k"]],[[15,30,"pl-s"],[15,16,"pl-pds"],[29,30,"pl-pds"],[32,39,"pl-v"],[39,40,"pl-k"],[40,49,"pl-s"],[40,41,"pl-pds"],[48,49,"pl-pds"],[51,60,"pl-v"],[60,61,"pl-k"],[61,70,"pl-s"],[61,62,"pl-pds"],[69,70,"pl-pds"]],[],[[0,5,"pl-c1"]],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,18,"pl-c1"],[18,19,"pl-s"],[22,23,"pl-s"],[23,40,"pl-c1"],[40,41,"pl-s"]],[[36,37,"pl-s"],[37,49,"pl-c1"],[49,50,"pl-s"],[53,54,"pl-s"],[54,66,"pl-c1"],[66,67,"pl-s"]],[],[],[[0,29,"pl-mh"],[3,29,"pl-en"]],[],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"],[53,54,"pl-s"],[54,68,"pl-c1"],[68,69,"pl-s"]],[],[],[[0,3,"pl-s"],[3,9,"pl-en"]],[[0,8,"pl-c"],[0,1,"pl-c"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[[7,8,"pl-k"]],[],[[0,7,"pl-c"],[0,1,"pl-c"]],[[0,4,"pl-k"],[16,22,"pl-k"]],[[3,4,"pl-k"]],[[0,3,"pl-s"]],[],[],[[0,1,"pl-v"],[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[19,20,"pl-s"],[20,33,"pl-c1"],[33,34,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"],[18,19,"pl-s"],[19,30,"pl-c1"],[30,31,"pl-s"]],[[0,1,"pl-v"],[15,16,"pl-s"],[16,35,"pl-c1"],[35,36,"pl-s"],[39,40,"pl-s"],[40,60,"pl-c1"],[60,61,"pl-s"]],[],[[0,26,"pl-mh"],[3,26,"pl-en"]],[],[],[],[],[[0,1,"pl-ml"],[5,6,"pl-ml"],[10,11,"pl-ml"],[17,18,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"],[12,13,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,16,"pl-c1"],[16,17,"pl-s"],[18,19,"pl-ml"],[20,21,"pl-s"],[21,33,"pl-c1"],[33,34,"pl-s"],[35,36,"pl-ml"],[61,62,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,25,"pl-c1"],[25,26,"pl-s"],[27,28,"pl-ml"],[29,30,"pl-s"],[30,56,"pl-c1"],[56,57,"pl-s"],[58,59,"pl-ml"],[87,88,"pl-s"],[88,97,"pl-c1"],[97,98,"pl-s"],[115,116,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"],[16,17,"pl-ml"],[18,19,"pl-s"],[19,27,"pl-c1"],[27,28,"pl-s"],[29,30,"pl-ml"],[64,65,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[20,21,"pl-ml"],[24,25,"pl-ml"],[77,78,"pl-s"],[78,86,"pl-c1"],[86,87,"pl-s"],[88,89,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[20,21,"pl-ml"],[24,25,"pl-ml"],[66,67,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,9,"pl-c1"],[9,10,"pl-s"],[11,12,"pl-ml"],[15,16,"pl-ml"],[43,44,"pl-s"],[44,53,"pl-c1"],[53,54,"pl-s"],[63,64,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"],[13,14,"pl-ml"],[17,18,"pl-ml"],[39,40,"pl-s"],[40,60,"pl-c1"],[60,61,"pl-s"],[62,63,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[17,18,"pl-ml"],[21,22,"pl-ml"],[57,58,"pl-ml"]],[[0,1,"pl-ml"],[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"],[15,16,"pl-ml"],[17,18,"pl-s"],[18,26,"pl-c1"],[26,27,"pl-s"],[33,34,"pl-s"],[34,68,"pl-c1"],[68,69,"pl-s"],[70,71,"pl-ml"],[116,117,"pl-s"],[117,129,"pl-c1"],[129,130,"pl-s"],[146,147,"pl-ml"]],[],[[0,10,"pl-mh"],[3,10,"pl-en"]],[],[]],"colorizedLines":null}},"title":"dstack/sdk/python/README.md at next · Dstack-TEE/dstack","appPayload":{},"meta":{"title":"dstack/sdk/python/README.md at next · Dstack-TEE/dstack"}}</script>
  <div data-target="react-app.reactRoot"><meta name="github-code-view-meta-stats" id="github-code-view-meta-stats" data-hydrostats="publish"/> <!-- --> <a hidden="" id="code-view-repo-link" href="/Dstack-TEE/dstack" data-discover="true"></a> <div class="d-none"></div><div><div style="--spacing:var(--spacing-none)" class="prc-PageLayout-PageLayoutRoot--KH-d" data-component="SplitPageLayout" data-has-sidebar="true"><div class="prc-PageLayout-SidebarWrapper-kLG4B CopilotSidePanelSidebar-module__SidePanel__L3O0C CopilotSidePanelSidebar-module__HiddenSidePanel__TBRGn" style="--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="end" data-sticky="true" data-responsive-variant="fullscreen"><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-SidebarVerticalDivider-0Rl0V" data-component="PageLayout.VerticalDivider" data-variant="line" data-position="end" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="450" aria-valuemax="768" aria-valuenow="544" aria-valuetext="Pane width 544 pixels" tabindex="0"></div></div><div class="prc-PageLayout-Sidebar-iciWg" data-component="SplitPageLayout.Sidebar" data-resizable="true" style="--spacing:var(--spacing-normal);--pane-min-width:450px;--pane-max-width:768px;--pane-width-custom:544px;--pane-width-size:var(--pane-width-custom);--pane-width:544px"><div class="height-full" data-testid="copilot-code-view-side-panel"><div id="copilot-side-panel-content" class="height-full"></div></div></div></div><div class="prc-PageLayout-PageLayoutWrapper-2BhU2" data-width="full"><div class="prc-PageLayout-PageLayoutContent-BneH9"><div id="repos-file-tree-sidebar" class="CodeViewFileTreeLayout-module__sidebar__n_Aau" tabindex="0"><div class="prc-PageLayout-PaneWrapper-pHPop ReposFileTreePane-module__Pane__rBZpI ReposFileTreePane-module__HideTree__AYZnm ReposFileTreePane-module__HidePane__VHAVt" style="--offset-header:0px;--spacing-row:var(--spacing-none);--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="start" data-sticky="true"><div class="prc-PageLayout-HorizontalDivider-JLVqp prc-PageLayout-PaneHorizontalDivider-9tbnE" data-component="PageLayout.HorizontalDivider" data-variant-regular="none" data-variant-narrow="none" data-position="start" style="--spacing-divider:var(--spacing-none);--spacing:var(--spacing-none)"></div><div class="prc-PageLayout-Pane-AyzHK" data-component="SplitPageLayout.Pane" data-resizable="true" style="--spacing:var(--spacing-none);--pane-min-width:256px;--pane-max-width:calc(100vw - var(--pane-max-width-diff));--pane-width-size:var(--pane-width-large);--pane-width:320px"></div><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-PaneVerticalDivider-le57g" data-component="PageLayout.VerticalDivider" data-variant-narrow="none" data-variant-regular="line" data-variant-wide="line" data-position="start" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="256" aria-valuemax="600" aria-valuenow="320" aria-valuetext="Pane width 320 pixels" tabindex="0"></div></div></div></div><div data-component="SplitPageLayout.Content" class="prc-PageLayout-ContentWrapper-gR9eG"><div class="prc-PageLayout-Content-xWL-A" data-width="full" style="--spacing:var(--spacing-none)"><div class="SharedPageLayout-module__content__IwGAp" data-selector="repos-split-pane-content" id="repos-split-pane-content" tabindex="0"> <!-- --> <div class="container CodeViewHeader-module__Box__JkPOb"><div class="CodeViewHeader-module__StickyHeader__Qn7UN" id="StickyHeader"><div class="CodeViewHeader-module__Box_1__SbNDV"><div class="CodeViewHeader-module__Box_2__TB46f"><div class="react-code-view-header-wrap--narrow CodeViewHeader-module__Box_3__q1zUL"><div class="CodeViewHeader-module__treeToggleWrapper__RQ__9"><h2 class="use-tree-pane-module__Heading__s4QbZ prc-Heading-Heading-MtWFE" data-component="Heading"><button data-component="Button" type="button" aria-label="Expand file tree" data-testid="expand-file-tree-button-mobile" class="prc-Button-ButtonBase-9n-Xk ExpandFileTreeButton-module__Button_1__Svs95" data-loading="false" data-size="medium" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-left" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Files</span></span></button><button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-controls="repos-file-tree" class="prc-Button-ButtonBase-9n-Xk position-relative ExpandFileTreeButton-module__expandButton__hDOcv ExpandFileTreeButton-module__filesButtonBreakpoint__zEvz3 fgColor-muted prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-labelledby="_R_4lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sidebar-collapse" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"></path><path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="se" data-component="Tooltip" aria-hidden="true" id="_R_4lla9lik5_">Expand file tree</span><div class="d-none"></div></h2></div><div class="react-code-view-header-mb--narrow mr-2"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="next branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector-wide"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">next</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="react-code-view-header-mb--narrow CodeViewHeader-module__Box_5__MQ0hL"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__lg__Rjz0A"><nav data-testid="breadcrumbs" aria-labelledby="repos-header-breadcrumb-heading" id="repos-header-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="repos-header-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/Dstack-TEE/dstack/tree/next" data-discover="true">dstack</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/Dstack-TEE/dstack/tree/next/sdk" data-discover="true">sdk</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/Dstack-TEE/dstack/tree/next/sdk/python" data-discover="true">python</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__lg__Rjz0A prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="file-name-id">README.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lla9lik5_">Copy path</span></div></div></div><div class="react-code-view-header-element--wide"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><div><div class="CodeViewHeader-module__FileResultsList__JDzUy"><span class="d-flex FileResultsList-module__FilesSearchBox__ivVkc TextInput-wrapper prc-components-TextInputWrapper-Hpdqi prc-components-TextInputBaseWrapper-wY-n0" data-no-trailing-action="true" data-component="TextInput" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id="_R_1cpla9lik5_" aria-hidden="true" data-component="TextInput.LeadingVisual"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellCheck="false" placeholder="Go to file" aria-describedby="_R_1cpla9lik5_ _R_1cpla9lik5H1_" data-component="input" class="prc-components-Input-IwWrt" value=""/><span class="TextInput-icon" id="_R_1cpla9lik5H1_" aria-hidden="true" data-component="TextInput.TrailingVisual"></span></span></div><div class="d-none"></div></div><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-wide" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7p9la9lik5_" id="_R_99la9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7p9la9lik5_">More file actions</span></div></div></div><div class="react-code-view-header-element--narrow"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-narrow" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7pdla9lik5_" id="_R_9dla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7pdla9lik5_">More file actions</span></div></div></div></div></div></div></div><div class="CodeView-module__contentWrapper__cG2JH"><div class="react-code-view-bottom-padding"><div class="BlobTopBanners-module__Box__v_nvx"></div></div> <div class="d-none"></div><div class="d-flex flex-column border rounded-2 tmp-mb-3 pl-1"><div class="LatestCommit-module__Box__B25ZT"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">History</h2><a data-component="LinkButton" href="/Dstack-TEE/dstack/commits/next/sdk/python/README.md" class="prc-Button-ButtonBase-9n-Xk d-none d-lg-flex LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><span class="fgColor-default">History</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><a data-component="LinkButton" aria-label="View commit history for this file." href="/Dstack-TEE/dstack/commits/next/sdk/python/README.md" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby="_R_4mlala9lik5_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" role="tooltip" aria-hidden="true" id="_R_4mlala9lik5_">History</span></div></div></div></div></div><div class="d-flex flex-row"><div class="container BlobViewContent-module__blobContainer__DtH2d"><div class="react-code-size-details-banner BlobViewContent-module__codeSizeDetails__e5sUw"><div class="react-code-size-details-banner CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="23.9 KB" style="--truncate-max-width:100%"><span>639 lines (482 loc) · 23.9 KB</span></div></div></div></div><div class="react-blob-view-header-sticky BlobViewContent-module__stickyHeader__VwxB5" id="repos-sticky-header"><div class="BlobViewHeader-module__Box__yhm9u"><div class="react-blob-sticky-header"><div class="FileNameStickyHeader-module__outerWrapper__ZL4Xc FileNameStickyHeader-module__outerWrapperHidden__Zpynk"><div class="FileNameStickyHeader-module__Box_1__Hazu5"><div class="FileNameStickyHeader-module__Box_2__hoolP"><div class="FileNameStickyHeader-module__Box_3__MVKsk"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="next branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">next</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="FileNameStickyHeader-module__Box_4__FLhtt"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__md__Wb1Gs"><nav data-testid="breadcrumbs" aria-labelledby="sticky-breadcrumb-heading" id="sticky-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="sticky-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/Dstack-TEE/dstack/tree/next" data-discover="true">dstack</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/Dstack-TEE/dstack/tree/next/sdk" data-discover="true">sdk</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/Dstack-TEE/dstack/tree/next/sdk/python" data-discover="true">python</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__md__Wb1Gs prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="sticky-file-name-id">README.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lcpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lcpala9lik5_">Copy path</span></div></div></div><button data-component="Button" type="button" class="prc-Button-ButtonBase-9n-Xk FileNameStickyHeader-module__Button__LSEU_ FileNameStickyHeader-module__GoToTopButton__nxAFn" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-up" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.47 7.78a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018L9 4.81v7.44a.75.75 0 0 1-1.5 0V4.81L4.53 7.78a.75.75 0 0 1-1.06 0Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Top</span></span></button></div></div></div><div class="BlobViewHeader-module__Box_1__VEmuQ"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">File metadata and controls</h2><div class="BlobViewHeader-module__Box_2__icUs2"><ul aria-label="File view" class="prc-SegmentedControl-SegmentedControl-lqIXp BlobTabButtons-module__SegmentedControl__jen2u" data-variant="default" data-size="small" data-component="SegmentedControl"><li class="prc-SegmentedControl-Item-tSCQh" data-selected="" data-component="SegmentedControl.Button"><button aria-pressed="true" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:transparent"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Preview">Preview</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Code">Code</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Blame">Blame</div></span></button></li></ul><div class="d-none"></div><div class="react-code-size-details-in-header CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="23.9 KB" style="--truncate-max-width:100%"><span>639 lines (482 loc) · 23.9 KB</span></div></div></div></div><div class="BlobViewHeader-module__Box_3__ng6v2"><div class="d-none"></div><div class="react-blob-header-edit-and-raw-actions BlobViewHeader-module__Box_4__J4Y4W"><div class="d-none"></div><div class="prc-ButtonGroup-ButtonGroup-vFUrY" data-component="ButtonGroup"><div class="prc-ButtonGroup-Item-PqvDl"><a data-component="LinkButton" href="https://github.com/Dstack-TEE/dstack/raw/refs/heads/next/sdk/python/README.md" data-testid="raw-button" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov BlobViewHeader-module__LinkButton__X9kx2" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Raw</span></span></a></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="copy-raw-button" class="prc-Button-ButtonBase-9n-Xk prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_qaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_qaucpala9lik5_">Copy raw file</span></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="download-raw-button" class="prc-Button-ButtonBase-9n-Xk BlobViewHeader-module__downloadButton__ef459 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_eaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-download" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"></path><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_eaucpala9lik5_">Download raw file</span></div></div></div><button data-component="IconButton" type="button" aria-pressed="false" class="prc-Button-ButtonBase-9n-Xk tmp-mr-2 TableOfContents-module__IconButton__jrlNM prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_3ucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_3ucpala9lik5_">Outline</span><div class="react-blob-header-edit-and-raw-actions-combined"><button data-component="IconButton" type="button" title="More file actions" data-testid="more-file-actions-button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click BlobViewHeader-module__IconButton__XrMQY prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_fkecpala9lik5_" id="_R_kecpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_fkecpala9lik5_">Edit and raw actions</span></div></div></div></div><div></div></div><div class="BlobViewContent-module__blobContentWrapper__JS0W6"><section aria-labelledby="file-name-id-wide file-name-id-mobile" class="BlobContent-module__blobContentSection__VOgZq BlobContent-module__blobContentSectionMarkdown__mPLOK" style="margin-top:46px"><div class="js-snippet-clipboard-copy-unpositioned BlobContent-module__markdownBlob__T8jpG" data-hpc="true" containertiming="hpc"><article class="markdown-body entry-content container-lg" itemprop="text"><div class="markdown-heading" dir="auto"><h1 tabindex="-1" class="heading-element" dir="auto">dstack SDK for Python</h1><a id="user-content-dstack-sdk-for-python" class="anchor" aria-label="Permalink: dstack SDK for Python" href="#dstack-sdk-for-python"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Access TEE features from your Python application running inside dstack. Derive deterministic keys, request attestations, and issue TLS certificates—all backed by hardware security.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">The default client speaks v1</h2><a id="user-content-the-default-client-speaks-v1" class="anchor" aria-label="Permalink: The default client speaks v1" href="#the-default-client-speaks-v1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">dstack 0.6.0 split the guest agent API into two surfaces on one socket, and the
agent picks between them by URL path alone. This SDK mirrors both, and nothing
more — neither client translates calls to the other.</p>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>Client</th>
<th>Surface</th>
<th>Paths</th>
<th>What it is</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>DstackClient</code> / <code>AsyncDstackClient</code> — same classes as <code>DstackClientV1</code> / <code>AsyncDstackClientV1</code></td>
<td><code>dstack.guest.v1</code></td>
<td><code>/v1/GetKey</code></td>
<td><strong>The default.</strong> Where every new capability lands</td>
</tr>
<tr>
<td><code>DstackClientV0</code> / <code>AsyncDstackClientV0</code></td>
<td>the frozen v0.5.11 API</td>
<td><code>/GetKey</code>, equivalently <code>/v0/GetKey</code></td>
<td>Legacy. Frozen: no new method, no new field, ever</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<p dir="auto">Use the unsuffixed name in new code. The <code>V1</code> names are the same classes, spelled
out for code that wants the surface visible at a glance.</p>
<div class="markdown-alert markdown-alert-warning" dir="auto"><p class="markdown-alert-title" dir="auto"><svg data-component="Octicon" class="octicon octicon-alert mr-2" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>Warning</p><p dir="auto"><strong>v1 derives different key material than v0.</strong> <code>DstackClient.get_key('x', 'secp256k1')</code>
and <code>DstackClientV0.get_key('x')</code> return different private keys. The v1 KDF binds
the algorithm and its own context tag alongside the domain, which is the point of
the new derivation, not a defect: v0 ignored the algorithm, so one secret served
two curves. There is no compatibility mode and no flag that brings the old bytes
back. An application that has published or committed to material derived from a v0
key must migrate deliberately — derive the v1 key, re-establish whatever depends on
the old one under it, and only then cut over.</p>
<p dir="auto">Code that used the unsuffixed client for v0 calls fails <strong>loudly</strong> on upgrade
rather than silently deriving different keys, because the v1 method signatures
differ and <code>get_key</code> requires <code>algorithm</code> explicitly. To stay on the frozen
surface, switch to <code>DstackClientV0</code>.</p>
</div>
<p dir="auto">The v1 surface serves only what genuinely needs the TEE, so it has no <code>sign</code>, no
<code>verify</code>, no <code>emit_event</code>, no <code>get_quote</code> and no <code>gpu_info</code>. See
<a href="/Dstack-TEE/dstack/blob/next/docs/guest-api-v1.md"><code>docs/guest-api-v1.md</code></a> for the normative spec, and
<a href="#legacy-v0-frozen">Legacy (v0, frozen)</a> for the surface those methods live on.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Installation</h2><a id="user-content-installation" class="anchor" aria-label="Permalink: Installation" href="#installation"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pip install dstack-sdk"><pre>pip install dstack-sdk</pre></div>
<p dir="auto">Blockchain helpers are optional extras, needed only for the v0-era chain
adapters (<a href="#blockchain-helpers">Blockchain helpers</a>):</p>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>Extra</th>
<th>Pulls in</th>
<th>Use when</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>dstack-sdk[ethereum]</code></td>
<td><code>eth-account</code></td>
<td>You sign Ethereum transactions</td>
</tr>
<tr>
<td><code>dstack-sdk[solana]</code></td>
<td><code>solders</code></td>
<td>You sign Solana transactions</td>
</tr>
<tr>
<td><code>dstack-sdk[all]</code></td>
<td>both</td>
<td>You need both</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<p dir="auto">Aliases <code>[eth]</code> and <code>[sol]</code> are accepted for convenience.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Quick Start</h2><a id="user-content-quick-start" class="anchor" aria-label="Permalink: Quick Start" href="#quick-start"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from dstack_sdk import DstackClient

client = DstackClient()

key = client.get_key('storage-encryption', 'secp256k1')   # algorithm is required
attestation = client.attest(b'my-app-state')
info = client.info()"><pre><span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-v">DstackClient</span>

<span class="pl-s1">client</span> <span class="pl-c1">=</span> <span class="pl-en">DstackClient</span>()

<span class="pl-s1">key</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'storage-encryption'</span>, <span class="pl-s">'secp256k1'</span>)   <span class="pl-c"># algorithm is required</span>
<span class="pl-s1">attestation</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">attest</span>(<span class="pl-s">b'my-app-state'</span>)
<span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">info</span>()</pre></div>
<p dir="auto">The client automatically connects to <code>/var/run/dstack.sock</code>. For local
development with the simulator:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="client = DstackClient('http://localhost:8090')
# or export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090"><pre><span class="pl-s1">client</span> <span class="pl-c1">=</span> <span class="pl-en">DstackClient</span>(<span class="pl-s">'http://localhost:8090'</span>)
<span class="pl-c"># or export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090</span></pre></div>
<p dir="auto">Every v1 method requires a 0.6.0+ guest agent: older agents have no <code>/v1</code> mount
and answer HTTP 404.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Client</h2><a id="user-content-client" class="anchor" aria-label="Permalink: Client" href="#client"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>DstackClient</code> speaks <code>dstack.guest.v1</code> at <code>/v1/&lt;Method&gt;</code>. Six methods, and
deliberately no more — v1 serves only what genuinely needs the TEE. In the
examples below, <code>client = DstackClient()</code>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>get_key()</code></h3><a id="user-content-get_key" class="anchor" aria-label="Permalink: get_key()" href="#get_key"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Derives deterministic keys bound to your application's identity (<code>app_id</code>). The
same domain always produces the same key for your app, and different apps get
different keys for the same domain.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="key = client.get_key('storage-encryption', 'secp256k1')
print(key.key)             # 32 raw bytes
print(key.public_key)      # SEC1 compressed (33 B), or 32 B for ed25519
print(key.signature_chain) # two links: app root, then KMS root"><pre><span class="pl-s1">key</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'storage-encryption'</span>, <span class="pl-s">'secp256k1'</span>)
<span class="pl-en">print</span>(<span class="pl-s1">key</span>.<span class="pl-c1">key</span>)             <span class="pl-c"># 32 raw bytes</span>
<span class="pl-en">print</span>(<span class="pl-s1">key</span>.<span class="pl-c1">public_key</span>)      <span class="pl-c"># SEC1 compressed (33 B), or 32 B for ed25519</span>
<span class="pl-en">print</span>(<span class="pl-s1">key</span>.<span class="pl-c1">signature_chain</span>) <span class="pl-c"># two links: app root, then KMS root</span></pre></div>
<p dir="auto">Every field the proto declares <code>bytes</code> is <code>bytes</code> here, hex only on the wire.
<code>public_key</code> in particular is what the v1 key claim commits to, and the claim is
built over raw bytes — passing a hex string would build it over 66 ASCII
characters and produce a chain that silently never verifies.</p>
<p dir="auto"><strong>Parameters:</strong></p>
<ul dir="auto">
<li><code>domain</code>: Any string. This replaces v0's <code>path</code> plus <code>purpose</code>; in v0 only <code>path</code> reached the KDF and <code>purpose</code> was merely echoed into the chain claim. Derivation is flat — two domains give unrelated keys, and <code>a/b</code> is not a child of <code>a</code>.</li>
<li><code>algorithm</code>: Exactly <code>'secp256k1'</code> or <code>'ed25519'</code>. <strong>Required.</strong> There is no default and no <code>k256</code> alias, because in v0 a typo silently produced a key of the wrong type under a name the caller thought meant something else. An empty value is rejected client-side.</li>
</ul>
<p dir="auto"><strong>Returns:</strong> <code>GetKeyResponseV1</code> with <code>key: bytes</code>, <code>public_key: bytes</code> and
<code>signature_chain: list[bytes]</code>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>attest()</code></h3><a id="user-content-attest" class="anchor" aria-label="Permalink: attest()" href="#attest"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">The sole CVM attestation entry point in v1. The dstack attestation format
already carries the quote and the event log, so v0's TDX-only <code>get_quote</code> has
nothing left to add.</p>
<p dir="auto"><code>report_data</code> is bytes, never <code>str</code>. v0 accepted a <code>str</code> and UTF-8 encoded it,
so <code>attest("deadbeef")</code> committed to the eight ASCII characters rather than the
four bytes they spell, with no error to say so; v1 makes you write
<code>value.encode()</code> or <code>bytes.fromhex(value)</code> at the call site, where it is visible
which one was meant. <code>attest_gpu</code>'s nonce is bytes only for the same reason.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="result = client.attest(b'user:alice:nonce123')
print(result.attestation)   # bytes

with_gpu = client.attest(b'user:alice:nonce123', include_boottime_gpu_evidence=True)
for bundle in with_gpu.boottime_gpu_evidence:
    print(bundle.vendor, bundle.format, bundle.evidence)"><pre><span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">attest</span>(<span class="pl-s">b'user:alice:nonce123'</span>)
<span class="pl-en">print</span>(<span class="pl-s1">result</span>.<span class="pl-c1">attestation</span>)   <span class="pl-c"># bytes</span>

<span class="pl-s1">with_gpu</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">attest</span>(<span class="pl-s">b'user:alice:nonce123'</span>, <span class="pl-s1">include_boottime_gpu_evidence</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
<span class="pl-k">for</span> <span class="pl-s1">bundle</span> <span class="pl-c1">in</span> <span class="pl-s1">with_gpu</span>.<span class="pl-c1">boottime_gpu_evidence</span>:
    <span class="pl-en">print</span>(<span class="pl-s1">bundle</span>.<span class="pl-c1">vendor</span>, <span class="pl-s1">bundle</span>.<span class="pl-c1">format</span>, <span class="pl-s1">bundle</span>.<span class="pl-c1">evidence</span>)</pre></div>
<p dir="auto"><code>report_data</code> is 1–64 bytes and is zero-padded on the right to 64.
<code>boottime_gpu_evidence</code> is a list of <code>GpuEvidenceBundleV1</code> — the same model
<code>attest_gpu()</code> returns, so one bundle parser serves both methods. It is empty
unless the flag was set and the guest has boot-time output; there is no
sentinel. Boot-time bundles carry <code>format='nvidia-nvattest-boottime-json-v1'</code>,
against <code>attest_gpu()</code>'s <code>'nvidia-nvattest-collect-evidence-json-v1'</code>.</p>
<p dir="auto">Boot-time evidence is <em>not</em> bound to <code>report_data</code> — nvattest ran at boot
against its own nonce. Bind it by replaying the runtime event log and comparing
sha256 of <code>bundle.evidence</code> against <code>evidence_sha256</code> in the measured
<code>gpu-attestation</code> event. <code>evidence</code> is the nvattest output byte for byte; do not
parse and re-serialize before hashing, since key order and whitespace change the
digest.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>attest_gpu()</code></h3><a id="user-content-attest_gpu" class="anchor" aria-label="Permalink: attest_gpu()" href="#attest_gpu"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Samples the GPU <em>now</em>, against a nonce you choose — which is what
<code>boottime_gpu_evidence</code> cannot tell you, since that is a record written at boot.
Use it after anything that may have reinitialised the GPU.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="result = client.attest_gpu(os.urandom(32))  # exactly 32 bytes
for bundle in result.bundles:
    print(bundle.vendor, bundle.format, bundle.evidence)"><pre><span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">attest_gpu</span>(<span class="pl-s1">os</span>.<span class="pl-c1">urandom</span>(<span class="pl-c1">32</span>))  <span class="pl-c"># exactly 32 bytes</span>
<span class="pl-k">for</span> <span class="pl-s1">bundle</span> <span class="pl-c1">in</span> <span class="pl-s1">result</span>.<span class="pl-c1">bundles</span>:
    <span class="pl-en">print</span>(<span class="pl-s1">bundle</span>.<span class="pl-c1">vendor</span>, <span class="pl-s1">bundle</span>.<span class="pl-c1">format</span>, <span class="pl-s1">bundle</span>.<span class="pl-c1">evidence</span>)</pre></div>
<p dir="auto">Select a verifier using each bundle's <code>vendor</code> and <code>format</code>, then check the
signature, certificate chain, measurements, and the nonce embedded in the
evidence. <code>evidence</code> is opaque vendor-native bytes, hex-encoded on the wire — do
not assume UTF-8 or JSON. It does not by itself bind the GPU to this CVM; only
TDISP/TEE-IO device binding closes that gap.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>issue_cert()</code></h3><a id="user-content-issue_cert" class="anchor" aria-label="Permalink: issue_cert()" href="#issue_cert"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">v0 called this <code>get_tls_key()</code>, which named the by-product rather than the
request. The private key is freshly generated per call and is <em>not</em> derived from
the app identity: two calls with the same arguments return two unrelated keys.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cert = client.issue_cert(
    subject='api.example.com',
    alt_names=['localhost'],
    usage_ra_tls=True,       # Embed the attestation in the certificate
    usage_server_auth=True,
    usage_client_auth=False,
    with_app_info=True,
    not_before=1700000000,   # seconds since UNIX epoch
    not_after=1800000000,
)
print(cert.key)                 # PEM private key
print(cert.certificate_chain)   # PEM chain, leaf first"><pre><span class="pl-s1">cert</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">issue_cert</span>(
    <span class="pl-s1">subject</span><span class="pl-c1">=</span><span class="pl-s">'api.example.com'</span>,
    <span class="pl-s1">alt_names</span><span class="pl-c1">=</span>[<span class="pl-s">'localhost'</span>],
    <span class="pl-s1">usage_ra_tls</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,       <span class="pl-c"># Embed the attestation in the certificate</span>
    <span class="pl-s1">usage_server_auth</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,
    <span class="pl-s1">usage_client_auth</span><span class="pl-c1">=</span><span class="pl-c1">False</span>,
    <span class="pl-s1">with_app_info</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,
    <span class="pl-s1">not_before</span><span class="pl-c1">=</span><span class="pl-c1">1700000000</span>,   <span class="pl-c"># seconds since UNIX epoch</span>
    <span class="pl-s1">not_after</span><span class="pl-c1">=</span><span class="pl-c1">1800000000</span>,
)
<span class="pl-en">print</span>(<span class="pl-s1">cert</span>.<span class="pl-c1">key</span>)                 <span class="pl-c"># PEM private key</span>
<span class="pl-en">print</span>(<span class="pl-s1">cert</span>.<span class="pl-c1">certificate_chain</span>)   <span class="pl-c"># PEM chain, leaf first</span></pre></div>
<p dir="auto"><strong>Returns:</strong> <code>IssueCertResponseV1</code> with a PEM <code>key</code> and a leaf-first
<code>certificate_chain</code>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>info()</code></h3><a id="user-content-info" class="anchor" aria-label="Permalink: info()" href="#info"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="info = client.info()
print(info.app_id, info.app_name, info.compose_hash)
print(info.instance_id, info.device_id)
print(info.os_image_hash, info.mr_aggregated)
print(info.app_compose, info.vm_config, info.key_provider_info)
print(info.cloud_vendor, info.cloud_product)"><pre><span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">info</span>()
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">app_id</span>, <span class="pl-s1">info</span>.<span class="pl-c1">app_name</span>, <span class="pl-s1">info</span>.<span class="pl-c1">compose_hash</span>)
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">instance_id</span>, <span class="pl-s1">info</span>.<span class="pl-c1">device_id</span>)
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">os_image_hash</span>, <span class="pl-s1">info</span>.<span class="pl-c1">mr_aggregated</span>)
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">app_compose</span>, <span class="pl-s1">info</span>.<span class="pl-c1">vm_config</span>, <span class="pl-s1">info</span>.<span class="pl-c1">key_provider_info</span>)
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">cloud_vendor</span>, <span class="pl-s1">info</span>.<span class="pl-c1">cloud_product</span>)</pre></div>
<p dir="auto">Identity and configuration — not attestation. Nothing here is evidence: it
arrives over a local socket with no quote behind it. That is why there is no
<code>tcb_info</code> and no <code>app_cert</code>. The measurement registers and the event log belong
to <code>attest()</code>, which returns them quote-backed. <code>compose_hash</code>, <code>os_image_hash</code>
and <code>mr_aggregated</code> are here because they identify <em>which</em> application and image
this is, and a relying party still confirms them against an attestation.</p>
<p dir="auto"><code>app_compose</code> is the verbatim deployed document and <code>compose_hash</code> is sha256
over exactly those bytes — do not parse and re-serialize before hashing.</p>
<p dir="auto"><code>app_id</code>, <code>instance_id</code>, <code>compose_hash</code>, <code>device_id</code>, <code>os_image_hash</code> and
<code>mr_aggregated</code> are <code>bytes</code>, matching the proto. Call <code>.hex()</code> to print one.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>version()</code></h3><a id="user-content-version" class="anchor" aria-label="Permalink: version()" href="#version"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="client.version()   # VersionResponseV1(version, rev)"><pre><span class="pl-s1">client</span>.<span class="pl-c1">version</span>()   <span class="pl-c"># VersionResponseV1(version, rev)</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Async</h3><a id="user-content-async" class="anchor" aria-label="Permalink: Async" href="#async"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>AsyncDstackClient</code> has the identical surface, with every method a coroutine:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import asyncio
from dstack_sdk import AsyncDstackClient

async def main():
    client = AsyncDstackClient()

    info = await client.info()
    key = await client.get_key('backup-signing', 'ed25519')

    # Run requests concurrently
    keys = await asyncio.gather(
        client.get_key('user/alice', 'secp256k1'),
        client.get_key('user/bob', 'secp256k1'),
    )

asyncio.run(main())"><pre><span class="pl-k">import</span> <span class="pl-s1">asyncio</span>
<span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-v">AsyncDstackClient</span>

<span class="pl-k">async</span> <span class="pl-k">def</span> <span class="pl-en">main</span>():
    <span class="pl-s1">client</span> <span class="pl-c1">=</span> <span class="pl-en">AsyncDstackClient</span>()

    <span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">client</span>.<span class="pl-c1">info</span>()
    <span class="pl-s1">key</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">client</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'backup-signing'</span>, <span class="pl-s">'ed25519'</span>)

    <span class="pl-c"># Run requests concurrently</span>
    <span class="pl-s1">keys</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">asyncio</span>.<span class="pl-c1">gather</span>(
        <span class="pl-s1">client</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'user/alice'</span>, <span class="pl-s">'secp256k1'</span>),
        <span class="pl-s1">client</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'user/bob'</span>, <span class="pl-s">'secp256k1'</span>),
    )

<span class="pl-s1">asyncio</span>.<span class="pl-c1">run</span>(<span class="pl-en">main</span>())</pre></div>
<p dir="auto"><code>AsyncDstackClient</code> accepts the same constructor as <code>DstackClient</code> plus
<code>use_sync_http: bool = False</code> for callers that need to issue sync HTTP from
within an async context. The same holds for the v0 clients.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Signing and verifying</h3><a id="user-content-signing-and-verifying" class="anchor" aria-label="Permalink: Signing and verifying" href="#signing-and-verifying"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Neither is a v1 method. Signing happens wherever the key is, and <code>get_key()</code>
already hands you the key, so a round trip to the agent adds nothing; verifying
needs no key at all, and an agent's answer arrives over the socket unattested,
so a relying party gains nothing over checking the signature itself with a
standard library.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from cryptography.hazmat.primitives.asymmetric import ed25519

key = client.get_key('signing/messages', 'ed25519')
signing_key = ed25519.Ed25519PrivateKey.from_private_bytes(key.key)
signature = signing_key.sign(b'message to sign')"><pre><span class="pl-k">from</span> <span class="pl-s1">cryptography</span>.<span class="pl-s1">hazmat</span>.<span class="pl-s1">primitives</span>.<span class="pl-s1">asymmetric</span> <span class="pl-k">import</span> <span class="pl-s1">ed25519</span>

<span class="pl-s1">key</span> <span class="pl-c1">=</span> <span class="pl-s1">client</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'signing/messages'</span>, <span class="pl-s">'ed25519'</span>)
<span class="pl-s1">signing_key</span> <span class="pl-c1">=</span> <span class="pl-s1">ed25519</span>.<span class="pl-c1">Ed25519PrivateKey</span>.<span class="pl-c1">from_private_bytes</span>(<span class="pl-s1">key</span>.<span class="pl-c1">key</span>)
<span class="pl-s1">signature</span> <span class="pl-c1">=</span> <span class="pl-s1">signing_key</span>.<span class="pl-c1">sign</span>(<span class="pl-s">b'message to sign'</span>)</pre></div>
<p dir="auto">To verify a v1 signature chain, follow
<a href="/Dstack-TEE/dstack/blob/next/docs/guest-api-v1.md"><code>docs/guest-api-v1.md</code></a>, which is the normative
spec: it gives the claim encoding, the link order, and — the part that actually
establishes anything — the requirement that the KMS root public key come from
somewhere you already trust (the <code>DstackKms</code> contract's <code>kmsInfo().k256Pubkey</code>,
or a value you pinned), never from the CVM being checked.</p>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Deployment Utilities</h2><a id="user-content-deployment-utilities" class="anchor" aria-label="Permalink: Deployment Utilities" href="#deployment-utilities"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">These utilities are for deployment scripts, not runtime SDK operations, and are
the same for either client.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Encrypted Environment Variables</h3><a id="user-content-encrypted-environment-variables" class="anchor" aria-label="Permalink: Encrypted Environment Variables" href="#encrypted-environment-variables"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">The KMS returns a fresh X25519 public key (with a secp256k1 signature) that you encrypt secrets against before submitting them with your deployment. Always verify the signer before trusting the key:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from dstack_sdk import (
    encrypt_env_vars,
    verify_env_encrypt_public_key,
    EnvVar,
)

# `public_key`, `signature_v1`, `timestamp` come from KMS /GetAppEnvEncryptPubKey.
signer = verify_env_encrypt_public_key(
    public_key=public_key_bytes,
    signature=signature_v1_bytes,
    app_id=app_id_hex,
    timestamp=timestamp,
)
if signer is None:
    raise RuntimeError('invalid KMS env-encrypt public key')

# Always compare the recovered signer against a known-good KMS signer
# address, obtained out-of-band from the DstackKms contract or your
# deployment configuration. Without this check, an attacker could sign
# their own env-encrypt key and the verification above would still pass.
EXPECTED_KMS_SIGNER = '0x...'  # replace with your known KMS signer address
if signer != EXPECTED_KMS_SIGNER:
    raise RuntimeError(
        f'unexpected KMS signer: got {signer}, '
        f'expected {EXPECTED_KMS_SIGNER}'
    )

env_vars = [
    EnvVar(key='DATABASE_URL', value='postgresql://...'),
    EnvVar(key='API_KEY', value='secret'),
]
encrypted = await encrypt_env_vars(env_vars, public_key_hex)
# encrypt_env_vars_sync(...) is also available for non-async callers."><pre><span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> (
    <span class="pl-s1">encrypt_env_vars</span>,
    <span class="pl-s1">verify_env_encrypt_public_key</span>,
    <span class="pl-v">EnvVar</span>,
)

<span class="pl-c"># `public_key`, `signature_v1`, `timestamp` come from KMS /GetAppEnvEncryptPubKey.</span>
<span class="pl-s1">signer</span> <span class="pl-c1">=</span> <span class="pl-en">verify_env_encrypt_public_key</span>(
    <span class="pl-s1">public_key</span><span class="pl-c1">=</span><span class="pl-s1">public_key_bytes</span>,
    <span class="pl-s1">signature</span><span class="pl-c1">=</span><span class="pl-s1">signature_v1_bytes</span>,
    <span class="pl-s1">app_id</span><span class="pl-c1">=</span><span class="pl-s1">app_id_hex</span>,
    <span class="pl-s1">timestamp</span><span class="pl-c1">=</span><span class="pl-s1">timestamp</span>,
)
<span class="pl-k">if</span> <span class="pl-s1">signer</span> <span class="pl-c1">is</span> <span class="pl-c1">None</span>:
    <span class="pl-k">raise</span> <span class="pl-en">RuntimeError</span>(<span class="pl-s">'invalid KMS env-encrypt public key'</span>)

<span class="pl-c"># Always compare the recovered signer against a known-good KMS signer</span>
<span class="pl-c"># address, obtained out-of-band from the DstackKms contract or your</span>
<span class="pl-c"># deployment configuration. Without this check, an attacker could sign</span>
<span class="pl-c"># their own env-encrypt key and the verification above would still pass.</span>
<span class="pl-c1">EXPECTED_KMS_SIGNER</span> <span class="pl-c1">=</span> <span class="pl-s">'0x...'</span>  <span class="pl-c"># replace with your known KMS signer address</span>
<span class="pl-k">if</span> <span class="pl-s1">signer</span> <span class="pl-c1">!=</span> <span class="pl-c1">EXPECTED_KMS_SIGNER</span>:
    <span class="pl-k">raise</span> <span class="pl-en">RuntimeError</span>(
        <span class="pl-s">f'unexpected KMS signer: got <span class="pl-s1"><span class="pl-kos">{</span><span class="pl-s1">signer</span><span class="pl-kos">}</span></span>, '</span>
        <span class="pl-s">f'expected <span class="pl-s1"><span class="pl-kos">{</span><span class="pl-c1">EXPECTED_KMS_SIGNER</span><span class="pl-kos">}</span></span>'</span>
    )

<span class="pl-s1">env_vars</span> <span class="pl-c1">=</span> [
    <span class="pl-en">EnvVar</span>(<span class="pl-s1">key</span><span class="pl-c1">=</span><span class="pl-s">'DATABASE_URL'</span>, <span class="pl-s1">value</span><span class="pl-c1">=</span><span class="pl-s">'postgresql://...'</span>),
    <span class="pl-en">EnvVar</span>(<span class="pl-s1">key</span><span class="pl-c1">=</span><span class="pl-s">'API_KEY'</span>, <span class="pl-s1">value</span><span class="pl-c1">=</span><span class="pl-s">'secret'</span>),
]
<span class="pl-s1">encrypted</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-en">encrypt_env_vars</span>(<span class="pl-s1">env_vars</span>, <span class="pl-s1">public_key_hex</span>)
<span class="pl-c"># encrypt_env_vars_sync(...) is also available for non-async callers.</span></pre></div>
<p dir="auto"><code>verify_env_encrypt_public_key</code> returns the recovered compressed secp256k1 signer (<code>0x</code>-prefixed hex) on success, or <code>None</code> for any failure (bad length, expired/future timestamp, malformed <code>app_id</code>, invalid signature). The default <code>max_age_seconds</code> is 300; pass a larger value if your deployment workflow legitimately holds the response longer.</p>
<p dir="auto"><code>verify_env_encrypt_public_key_legacy</code> remains available only for deployments that explicitly support older KMS builds without <code>signature_v1</code>. It does not provide timestamp replay protection and should not be used for new deployments.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Calculate Compose Hash</h3><a id="user-content-calculate-compose-hash" class="anchor" aria-label="Permalink: Calculate Compose Hash" href="#calculate-compose-hash"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from dstack_sdk import get_compose_hash

hash_value = get_compose_hash(app_compose_dict)"><pre><span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-s1">get_compose_hash</span>

<span class="pl-s1">hash_value</span> <span class="pl-c1">=</span> <span class="pl-en">get_compose_hash</span>(<span class="pl-s1">app_compose_dict</span>)</pre></div>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Compatibility</h2><a id="user-content-compatibility" class="anchor" aria-label="Permalink: Compatibility" href="#compatibility"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>Feature</th>
<th>Required dstack OS</th>
</tr>
</thead>
<tbody>
<tr>
<td>Every <code>DstackClient</code> (v1) method</td>
<td>0.6.0+ — older agents have no <code>/v1</code> mount and answer HTTP 404</td>
</tr>
<tr>
<td>V0 <code>get_key</code>, <code>get_quote</code>, <code>get_tls_key</code> (legacy fields), <code>info</code> (legacy fields)</td>
<td>0.3+</td>
</tr>
<tr>
<td>V0 <code>attest</code>, <code>sign</code>, <code>verify</code>, <code>is_reachable</code></td>
<td>0.5.0+ (<code>sign</code> requires a server build with the feature)</td>
</tr>
<tr>
<td>V0 <code>version</code>, <code>algorithm='ed25519'</code> on <code>get_key</code>, <code>info.cloud_vendor</code> / <code>cloud_product</code>, <code>not_before</code> / <code>not_after</code> / <code>with_app_info</code> on <code>get_tls_key</code></td>
<td>0.5.7+</td>
</tr>
<tr>
<td>V0 <code>emit_event</code></td>
<td>Removed in 0.6.0: the agent always fails it</td>
</tr>
<tr>
<td><code>verify_env_encrypt_public_key</code> (signature_v1 with timestamp)</td>
<td>Requires KMS build that emits <code>signature_v1</code>; legacy variant remains available</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<p dir="auto">V0 calls that require 0.5.7-only fields probe the <code>Version</code> RPC first and raise a clear <code>RuntimeError</code> on older guest agents. The v1 client never probes: it requires a 0.6 agent outright.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Development</h2><a id="user-content-development" class="anchor" aria-label="Permalink: Development" href="#development"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">For local development without TDX hardware, use the simulator:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="git clone https://github.com/Dstack-TEE/dstack.git
cd dstack/sdk/simulator
./build.sh
./dstack-simulator"><pre>git clone https://github.com/Dstack-TEE/dstack.git
<span class="pl-c1">cd</span> dstack/sdk/simulator
./build.sh
./dstack-simulator</pre></div>
<p dir="auto">Then set the endpoint:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090"><pre><span class="pl-k">export</span> DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090</pre></div>
<p dir="auto">Install dev dependencies, then run the tests and the format/lint checks with PDM:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cd sdk/python
pdm install --dev
pdm run test
pdm run check"><pre><span class="pl-c1">cd</span> sdk/python
pdm install --dev
pdm run <span class="pl-c1">test</span>
pdm run check</pre></div>
<p dir="auto"><code>make install</code> / <code>make test</code> wrap the same commands and additionally assert that
<code>DSTACK_SIMULATOR_ENDPOINT</code> and <code>TAPPD_SIMULATOR_ENDPOINT</code> are set.</p>
<hr>
<div class="markdown-heading" dir="auto"><h1 tabindex="-1" class="heading-element" dir="auto">Legacy (v0, frozen)</h1><a id="user-content-legacy-v0-frozen" class="anchor" aria-label="Permalink: Legacy (v0, frozen)" href="#legacy-v0-frozen"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Everything below is the frozen v0.5.11 surface. It still works and is still
served, but it gains no method and no field. Reach for it when you must keep the
v0 key derivation, or when you need <code>sign</code> / <code>verify</code>, which v1 does not serve.</p>
<p dir="auto">Import it by its explicit name — the unsuffixed <code>DstackClient</code> now means v1:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from dstack_sdk import DstackClientV0, AsyncDstackClientV0

v0 = DstackClientV0()"><pre><span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-v">DstackClientV0</span>, <span class="pl-v">AsyncDstackClientV0</span>

<span class="pl-s1">v0</span> <span class="pl-c1">=</span> <span class="pl-en">DstackClientV0</span>()</pre></div>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">V0 Client</h2><a id="user-content-v0-client" class="anchor" aria-label="Permalink: V0 Client" href="#v0-client"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">In the examples below, <code>v0 = DstackClientV0()</code>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Derive Keys</h3><a id="user-content-derive-keys" class="anchor" aria-label="Permalink: Derive Keys" href="#derive-keys"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>get_key()</code> derives deterministic keys bound to your application's identity (<code>app_id</code>). The same path always produces the same key for your app, but different apps get different keys even with the same path.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# Derive keys by path
eth_key = v0.get_key('wallet/ethereum')
btc_key = v0.get_key('wallet/bitcoin')

# Use path to separate keys
mainnet_key = v0.get_key('wallet/eth/mainnet')
testnet_key = v0.get_key('wallet/eth/testnet')

# Use a different signature algorithm (requires dstack OS &gt;= 0.5.7)
ed_key = v0.get_key('signing/key', algorithm='ed25519')"><pre><span class="pl-c"># Derive keys by path</span>
<span class="pl-s1">eth_key</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'wallet/ethereum'</span>)
<span class="pl-s1">btc_key</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'wallet/bitcoin'</span>)

<span class="pl-c"># Use path to separate keys</span>
<span class="pl-s1">mainnet_key</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'wallet/eth/mainnet'</span>)
<span class="pl-s1">testnet_key</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'wallet/eth/testnet'</span>)

<span class="pl-c"># Use a different signature algorithm (requires dstack OS &gt;= 0.5.7)</span>
<span class="pl-s1">ed_key</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'signing/key'</span>, <span class="pl-s1">algorithm</span><span class="pl-c1">=</span><span class="pl-s">'ed25519'</span>)</pre></div>
<p dir="auto"><strong>Parameters:</strong></p>
<ul dir="auto">
<li><code>path</code> (optional): Key derivation path. Defaults to <code>""</code> (root).</li>
<li><code>purpose</code> (optional): Included in the signature chain message; does not affect the derived key.</li>
<li><code>algorithm</code> (optional): <code>'secp256k1'</code> (default) or <code>'ed25519'</code>. For compatibility, this selects how the same derived 32-byte material is interpreted; it does not domain-separate the derivation. Use algorithm-specific paths when independent keys are required.</li>
</ul>
<p dir="auto"><strong>Returns:</strong> <code>GetKeyResponse</code></p>
<ul dir="auto">
<li><code>key</code>: Hex-encoded private key</li>
<li><code>signature_chain</code>: Signatures proving the key was derived in a genuine TEE</li>
<li><code>decode_key()</code> / <code>decode_signature_chain()</code>: Helpers that return <code>bytes</code></li>
</ul>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Generate Attestation Quotes</h3><a id="user-content-generate-attestation-quotes" class="anchor" aria-label="Permalink: Generate Attestation Quotes" href="#generate-attestation-quotes"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>get_quote()</code> creates a TDX quote proving your code runs in a genuine TEE.
It needs Intel TDX: without it the call fails, and on GCP Confidential VMs it
returns the TDX quote alone, leaving out the vTPM quote GCP's verification also
binds. Call <code>attest()</code> in both cases.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="quote = v0.get_quote(b'user:alice:nonce123')
print(quote.event_log)"><pre><span class="pl-s1">quote</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_quote</span>(<span class="pl-s">b'user:alice:nonce123'</span>)
<span class="pl-en">print</span>(<span class="pl-s1">quote</span>.<span class="pl-c1">event_log</span>)</pre></div>
<p dir="auto"><strong>Parameters:</strong></p>
<ul dir="auto">
<li><code>report_data</code>: Up to 64 bytes (<code>bytes</code> or <code>str</code>). Shorter inputs are padded with zeros; longer inputs should be hashed first (e.g., SHA-256).</li>
</ul>
<p dir="auto"><strong>Returns:</strong> <code>GetQuoteResponse</code></p>
<ul dir="auto">
<li><code>quote</code>: Hex-encoded TDX quote</li>
<li><code>event_log</code>: JSON string of measured events</li>
<li><code>decode_quote()</code> / <code>decode_event_log()</code>: Helpers</li>
</ul>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Versioned Attestation</h3><a id="user-content-versioned-attestation" class="anchor" aria-label="Permalink: Versioned Attestation" href="#versioned-attestation"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>attest()</code> returns a versioned attestation payload that newer verifier APIs can dispatch on without sniffing the quote format.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="result = v0.attest(b'user:alice:nonce123')
print(result.attestation)        # hex string
print(result.decode_attestation())  # bytes"><pre><span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">attest</span>(<span class="pl-s">b'user:alice:nonce123'</span>)
<span class="pl-en">print</span>(<span class="pl-s1">result</span>.<span class="pl-c1">attestation</span>)        <span class="pl-c"># hex string</span>
<span class="pl-en">print</span>(<span class="pl-s1">result</span>.<span class="pl-c1">decode_attestation</span>())  <span class="pl-c"># bytes</span></pre></div>
<p dir="auto"><code>report_data</code> is the only argument. GPU evidence — boot-time and on-demand alike —
is a v1 capability; see <a href="#attest"><code>attest()</code></a> and <a href="#attest_gpu"><code>attest_gpu()</code></a>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Get Instance Info</h3><a id="user-content-get-instance-info" class="anchor" aria-label="Permalink: Get Instance Info" href="#get-instance-info"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="info = v0.info()
print(info.app_id)
print(info.instance_id)
print(info.tcb_info)
print(info.cloud_vendor, info.cloud_product)  # 0.5.7+"><pre><span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">info</span>()
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">app_id</span>)
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">instance_id</span>)
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">tcb_info</span>)
<span class="pl-en">print</span>(<span class="pl-s1">info</span>.<span class="pl-c1">cloud_vendor</span>, <span class="pl-s1">info</span>.<span class="pl-c1">cloud_product</span>)  <span class="pl-c"># 0.5.7+</span></pre></div>
<p dir="auto"><strong>Returns:</strong> <code>InfoResponse</code></p>
<ul dir="auto">
<li><code>app_id</code>, <code>instance_id</code>, <code>app_name</code>, <code>device_id</code></li>
<li><code>tcb_info</code>: TCB measurements (MRTD, RTMRs, event log, compose hash, ...)</li>
<li><code>compose_hash</code>: Hash of the app configuration</li>
<li><code>app_cert</code>: Application certificate (PEM)</li>
<li><code>key_provider_info</code>: Key management configuration</li>
<li><code>cloud_vendor</code> / <code>cloud_product</code>: Cloud provider strings (empty on older OS)</li>
</ul>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Generate TLS Certificates</h3><a id="user-content-generate-tls-certificates" class="anchor" aria-label="Permalink: Generate TLS Certificates" href="#generate-tls-certificates"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>get_tls_key()</code> creates fresh TLS certificates. Unlike <code>get_key()</code>, each call generates a new random key.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="tls = v0.get_tls_key(
    subject='api.example.com',
    alt_names=['localhost'],
    usage_ra_tls=True,    # Embed attestation in certificate
    # 0.5.7+ options below:
    not_before=1700000000,   # seconds since UNIX epoch
    not_after=1800000000,
    with_app_info=True,
)
print(tls.key)                  # PEM private key
print(tls.certificate_chain)    # Certificate chain"><pre><span class="pl-s1">tls</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_tls_key</span>(
    <span class="pl-s1">subject</span><span class="pl-c1">=</span><span class="pl-s">'api.example.com'</span>,
    <span class="pl-s1">alt_names</span><span class="pl-c1">=</span>[<span class="pl-s">'localhost'</span>],
    <span class="pl-s1">usage_ra_tls</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,    <span class="pl-c"># Embed attestation in certificate</span>
    <span class="pl-c"># 0.5.7+ options below:</span>
    <span class="pl-s1">not_before</span><span class="pl-c1">=</span><span class="pl-c1">1700000000</span>,   <span class="pl-c"># seconds since UNIX epoch</span>
    <span class="pl-s1">not_after</span><span class="pl-c1">=</span><span class="pl-c1">1800000000</span>,
    <span class="pl-s1">with_app_info</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,
)
<span class="pl-en">print</span>(<span class="pl-s1">tls</span>.<span class="pl-c1">key</span>)                  <span class="pl-c"># PEM private key</span>
<span class="pl-en">print</span>(<span class="pl-s1">tls</span>.<span class="pl-c1">certificate_chain</span>)    <span class="pl-c"># Certificate chain</span></pre></div>
<p dir="auto"><strong>Parameters:</strong></p>
<ul dir="auto">
<li><code>subject</code> (optional): Certificate Common Name (e.g., domain name)</li>
<li><code>alt_names</code> (optional): Subject Alternative Names</li>
<li><code>usage_ra_tls</code> (optional): Embed TDX quote in a certificate extension (default <code>False</code>)</li>
<li><code>usage_server_auth</code> (optional): Enable for server authentication (default <code>True</code>)</li>
<li><code>usage_client_auth</code> (optional): Enable for client authentication (default <code>False</code>)</li>
<li><code>not_before</code> / <code>not_after</code> (optional, kw-only): Validity window in seconds since UNIX epoch. Requires dstack OS &gt;= 0.5.7.</li>
<li><code>with_app_info</code> (optional, kw-only): Embed app identity into the certificate. Requires dstack OS &gt;= 0.5.7.</li>
</ul>
<p dir="auto">When any of the 0.5.7-only options is set, the SDK probes <code>Version</code> first and raises <code>RuntimeError</code> on older guest agents that lack it.</p>
<p dir="auto"><strong>Returns:</strong> <code>GetTlsKeyResponse</code></p>
<ul dir="auto">
<li><code>key</code>: PEM-encoded private key</li>
<li><code>certificate_chain</code>: List of PEM certificates</li>
<li><code>as_uint8array(max_length=None)</code>: Returns the DER-encoded private key bytes (handy when feeding key material into low-level crypto libraries)</li>
</ul>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Sign and Verify</h3><a id="user-content-sign-and-verify" class="anchor" aria-label="Permalink: Sign and Verify" href="#sign-and-verify"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Both are frozen v0 RPCs and neither has a v1 counterpart.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="result = v0.sign('ed25519', b'message to sign')

verdict = v0.verify(
    'ed25519',
    b'message to sign',
    result.decode_signature(),
    result.decode_public_key(),
)
assert verdict.valid is True"><pre><span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">sign</span>(<span class="pl-s">'ed25519'</span>, <span class="pl-s">b'message to sign'</span>)

<span class="pl-s1">verdict</span> <span class="pl-c1">=</span> <span class="pl-s1">v0</span>.<span class="pl-c1">verify</span>(
    <span class="pl-s">'ed25519'</span>,
    <span class="pl-s">b'message to sign'</span>,
    <span class="pl-s1">result</span>.<span class="pl-c1">decode_signature</span>(),
    <span class="pl-s1">result</span>.<span class="pl-c1">decode_public_key</span>(),
)
<span class="pl-k">assert</span> <span class="pl-s1">verdict</span>.<span class="pl-c1">valid</span> <span class="pl-c1">is</span> <span class="pl-c1">True</span></pre></div>
<p dir="auto"><strong><code>sign()</code> Parameters:</strong></p>
<ul dir="auto">
<li><code>algorithm</code>: <code>'ed25519'</code>, <code>'secp256k1'</code> (alias <code>'k256'</code>), or <code>'secp256k1_prehashed'</code></li>
<li><code>data</code>: Data to sign (<code>bytes</code> or <code>str</code>). For <code>secp256k1_prehashed</code>, must be a 32-byte digest.</li>
</ul>
<p dir="auto"><strong><code>sign()</code> Returns:</strong> <code>SignResponse</code></p>
<ul dir="auto">
<li><code>signature</code>: Hex-encoded signature</li>
<li><code>public_key</code>: Hex-encoded public key</li>
<li><code>signature_chain</code>: Three signatures linking the signing key back to the KMS root</li>
</ul>
<p dir="auto"><strong><code>verify()</code> Returns:</strong> <code>VerifyResponse</code> with a single <code>valid: bool</code>. It reports
only whether that one signature matches that one public key — it says nothing
about <em>whose</em> key it is, and it does not walk the signature chain.</p>
<p dir="auto">Earlier drafts of this SDK shipped local <code>verify_signature</code> and
<code>verify_signature_chain</code> helpers. They are gone; verify locally per
<a href="/Dstack-TEE/dstack/blob/next/docs/guest-api-v1.md"><code>docs/guest-api-v1.md</code></a>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Diagnostics</h3><a id="user-content-diagnostics" class="anchor" aria-label="Permalink: Diagnostics" href="#diagnostics"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="v0.version()        # VersionResponse(version, rev) — raises on OS &lt; 0.5.7
v0.is_reachable()   # Quick connectivity probe; never raises"><pre><span class="pl-s1">v0</span>.<span class="pl-c1">version</span>()        <span class="pl-c"># VersionResponse(version, rev) — raises on OS &lt; 0.5.7</span>
<span class="pl-s1">v0</span>.<span class="pl-c1">is_reachable</span>()   <span class="pl-c"># Quick connectivity probe; never raises</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Async</h3><a id="user-content-async-1" class="anchor" aria-label="Permalink: Async" href="#async-1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>AsyncDstackClientV0</code> has the identical surface, with every method a coroutine:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import asyncio
from dstack_sdk import AsyncDstackClientV0

async def main():
    v0 = AsyncDstackClientV0()

    info = await v0.info()
    key = await v0.get_key('wallet/eth')

    # Run requests concurrently
    keys = await asyncio.gather(
        v0.get_key('user/alice'),
        v0.get_key('user/bob'),
    )

asyncio.run(main())"><pre><span class="pl-k">import</span> <span class="pl-s1">asyncio</span>
<span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-v">AsyncDstackClientV0</span>

<span class="pl-k">async</span> <span class="pl-k">def</span> <span class="pl-en">main</span>():
    <span class="pl-s1">v0</span> <span class="pl-c1">=</span> <span class="pl-en">AsyncDstackClientV0</span>()

    <span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">v0</span>.<span class="pl-c1">info</span>()
    <span class="pl-s1">key</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'wallet/eth'</span>)

    <span class="pl-c"># Run requests concurrently</span>
    <span class="pl-s1">keys</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">asyncio</span>.<span class="pl-c1">gather</span>(
        <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'user/alice'</span>),
        <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'user/bob'</span>),
    )

<span class="pl-s1">asyncio</span>.<span class="pl-c1">run</span>(<span class="pl-en">main</span>())</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Removed in 0.6.0</h3><a id="user-content-removed-in-060" class="anchor" aria-label="Permalink: Removed in 0.6.0" href="#removed-in-060"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>emit_event()</code> is still on the client, but the agent now fails every call:
runtime RTMR3 events are system-owned and an app can no longer extend them. The
method remains so that a caller written against 0.5.x gets the agent's own
explanation rather than a 404. <code>attest_gpu()</code> and <code>gpu_info()</code> never shipped on
this surface and are not here; they live on the v1 client.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Blockchain helpers</h2><a id="user-content-blockchain-helpers" class="anchor" aria-label="Permalink: Blockchain helpers" href="#blockchain-helpers"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">The chain adapters are v0-era. <code>dstack_sdk.ethereum</code> and <code>dstack_sdk.solana</code>
take a v0 <code>GetKeyResponse</code> or <code>GetTlsKeyResponse</code>, and that is the only shape
they take: v1 has no chain-related surface. <code>get_key()</code> returns key material,
and what an application builds out of those bytes is its own business.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from dstack_sdk import DstackClientV0
from dstack_sdk.ethereum import to_account_secure
from dstack_sdk.solana import to_keypair_secure

v0 = DstackClientV0()

account = to_account_secure(v0.get_key('wallet/ethereum'))
print(account.address)

keypair = to_keypair_secure(
    v0.get_key('wallet/solana', purpose='mainnet', algorithm='ed25519')
)
print(keypair.pubkey())"><pre><span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-v">DstackClientV0</span>
<span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span>.<span class="pl-s1">ethereum</span> <span class="pl-k">import</span> <span class="pl-s1">to_account_secure</span>
<span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span>.<span class="pl-s1">solana</span> <span class="pl-k">import</span> <span class="pl-s1">to_keypair_secure</span>

<span class="pl-s1">v0</span> <span class="pl-c1">=</span> <span class="pl-en">DstackClientV0</span>()

<span class="pl-s1">account</span> <span class="pl-c1">=</span> <span class="pl-en">to_account_secure</span>(<span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'wallet/ethereum'</span>))
<span class="pl-en">print</span>(<span class="pl-s1">account</span>.<span class="pl-c1">address</span>)

<span class="pl-s1">keypair</span> <span class="pl-c1">=</span> <span class="pl-en">to_keypair_secure</span>(
    <span class="pl-s1">v0</span>.<span class="pl-c1">get_key</span>(<span class="pl-s">'wallet/solana'</span>, <span class="pl-s1">purpose</span><span class="pl-c1">=</span><span class="pl-s">'mainnet'</span>, <span class="pl-s1">algorithm</span><span class="pl-c1">=</span><span class="pl-s">'ed25519'</span>)
)
<span class="pl-en">print</span>(<span class="pl-s1">keypair</span>.<span class="pl-c1">pubkey</span>())</pre></div>
<p dir="auto"><code>to_account_secure</code> / <code>to_keypair_secure</code> hash the full key material with
SHA-256 before deriving. The legacy <code>to_account()</code> / <code>to_keypair()</code> use raw key
bytes and are kept only for backward compatibility.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Migration from TappdClient</h2><a id="user-content-migration-from-tappdclient" class="anchor" aria-label="Permalink: Migration from TappdClient" href="#migration-from-tappdclient"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>TappdClient</code> only ever spoke v0, so replace it with <code>DstackClientV0</code> —
not with the unsuffixed name, which is now v1 and derives different keys:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# Before
from dstack_sdk import TappdClient
client = TappdClient()

# After
from dstack_sdk import DstackClientV0
v0 = DstackClientV0()"><pre><span class="pl-c"># Before</span>
<span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-v">TappdClient</span>
<span class="pl-s1">client</span> <span class="pl-c1">=</span> <span class="pl-en">TappdClient</span>()

<span class="pl-c"># After</span>
<span class="pl-k">from</span> <span class="pl-s1">dstack_sdk</span> <span class="pl-k">import</span> <span class="pl-v">DstackClientV0</span>
<span class="pl-s1">v0</span> <span class="pl-c1">=</span> <span class="pl-en">DstackClientV0</span>()</pre></div>
<p dir="auto">Method changes:</p>
<ul dir="auto">
<li><code>derive_key()</code> → <code>get_tls_key()</code> for TLS certificates</li>
<li><code>tdx_quote()</code> → <code>get_quote()</code> (raw data only, no hash algorithms)</li>
<li>Socket path: <code>/var/run/tappd.sock</code> → <code>/var/run/dstack.sock</code></li>
</ul>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Migration from v0 to v1</h2><a id="user-content-migration-from-v0-to-v1" class="anchor" aria-label="Permalink: Migration from v0 to v1" href="#migration-from-v0-to-v1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">v1 is a separate surface, not an upgrade path — read the key warning at the top
before switching anything that holds state.</p>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>v0</th>
<th>v1</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>get_tls_key()</code></td>
<td><code>issue_cert()</code></td>
<td>Renamed; same behaviour</td>
</tr>
<tr>
<td><code>get_key(path, purpose)</code></td>
<td><code>get_key(domain, algorithm)</code></td>
<td>Merged into one KDF input; <code>algorithm</code> is now required</td>
</tr>
<tr>
<td><code>get_quote()</code></td>
<td><code>attest()</code></td>
<td>The TDX-only channel is subsumed</td>
</tr>
<tr>
<td><code>info().tcb_info</code></td>
<td>—</td>
<td>Measurements are typed fields; the rest belongs to <code>attest()</code></td>
</tr>
<tr>
<td><code>info().app_cert</code></td>
<td>—</td>
<td>A dashboard artifact; it proved nothing</td>
</tr>
<tr>
<td><code>sign()</code></td>
<td>—</td>
<td>Sign locally with the key <code>get_key()</code> returns</td>
</tr>
<tr>
<td><code>verify()</code></td>
<td>—</td>
<td>Verify locally, per <code>docs/guest-api-v1.md</code></td>
</tr>
<tr>
<td><code>emit_event()</code></td>
<td>—</td>
<td>RTMR3 is system-owned as of 0.6.0</td>
</tr>
<tr>
<td><code>gpu_info()</code></td>
<td><code>attest()</code> with <code>include_boottime_gpu_evidence=True</code></td>
<td>Same bytes, now on the attestation call, in <code>attest_gpu()</code>'s bundle shape</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">License</h2><a id="user-content-license" class="anchor" aria-label="Permalink: License" href="#license"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Apache License 2.0</p>
</article></div><div class="d-none"></div></section></div></div></div> </div> <!-- --> </div></div></div></div></div></div><div class="ScrollMarksContainer-module__scrollMarksContainer__Eu7uU" id="find-result-marks-container"></div><div class="d-none"></div><div class="d-none"></div></div> <!-- --> <!-- --> </div>
</react-app>




  </div>

</turbo-frame>

    </main>
  </div>

  </div>

          <footer class="footer f6 color-fg-muted color-border-subtle tmp-pt-7 tmp-pb-6 p-responsive" role="contentinfo"  >
  <h2 class='sr-only'>Footer</h2>

  


  <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap">
    <div class="d-flex flex-items-center flex-shrink-0 mx-2">
      <a aria-label="GitHub Homepage" class="footer-octicon mr-2" href="https://github.com">
        <svg aria-hidden="true" data-component="Octicon" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github">
    <path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path>
</svg>
</a>
      <span>
        &copy; 2026 GitHub,&nbsp;Inc.
      </span>
    </div>

    <nav aria-label="Footer">
      <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3>

      <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading">


          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to Terms&quot;,&quot;label&quot;:&quot;text:terms&quot;}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to privacy&quot;,&quot;label&quot;:&quot;text:privacy&quot;}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a>
          </li>


            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to security&quot;,&quot;label&quot;:&quot;text:security&quot;}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a>
            </li>

            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to status&quot;,&quot;label&quot;:&quot;text:status&quot;}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a>
            </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to community&quot;,&quot;label&quot;:&quot;text:community&quot;}" href="https://github.community/" data-view-component="true" class="Link--secondary Link">Community</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to docs&quot;,&quot;label&quot;:&quot;text:docs&quot;}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to contact&quot;,&quot;label&quot;:&quot;text:contact&quot;}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a>
          </li>

          
<li class="mx-2" >
  <cookie-consent-link>
    <button
      type="button"
      class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent"
      data-action="click:cookie-consent-link#showConsentManagement"
      data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;cookies&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;cookies_link_subfooter_footer&quot;}"
    >
      Manage cookies
    </button>
  </cookie-consent-link>
</li>

  <li class="mx-2">
    <cookie-consent-link>
      <button
        type="button"
        class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent text-left"
        data-action="click:cookie-consent-link#showConsentManagement"
        data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;dont_share_info&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;dont_share_info_link_subfooter_footer&quot;}"
      >
        Do not share my personal information
      </button>
    </cookie-consent-link>
  </li>

      </ul>
    </nav>
  </div>
</footer>



    <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999"
      data-locale="en"
      data-initial-cookie-consent-allowed=""
      data-cookie-consent-required="true"
    ></ghcc-consent>




  <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden>
    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    You can’t perform that action at this time.
  </div>

    <template id="site-details-dialog">
  <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open>
    <summary role="button" aria-label="Close dialog"></summary>
    <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal">
      <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog>
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
      </button>
      <div class="octocat-spinner tmp-my-6 js-details-dialog-spinner"></div>
    </details-dialog>
  </details>
</template>

    <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;">
  <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;">
  </div>
</div>

    <template id="snippet-clipboard-copy-button">
  <div class="zeroclipboard-container position-absolute right-0 top-0">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2 tmp-m-2">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2 tmp-m-2">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>
<template id="snippet-clipboard-copy-button-unpositioned">
  <div class="zeroclipboard-container">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>




    </div>
    <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div>
    <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div>
  </body>
</html>

