phala-cloud 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- phala_cloud-0.4.0/CHANGELOG.md +115 -0
- phala_cloud-0.4.0/PKG-INFO +234 -0
- phala_cloud-0.4.0/README.md +202 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/pyproject.toml +4 -2
- phala_cloud-0.4.0/src/phala_cloud/__init__.py +152 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/action_responses.py +73 -4
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/actions.py +226 -21
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/client.py +62 -6
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/full_client.py +864 -219
- phala_cloud-0.4.0/src/phala_cloud/log_time.py +73 -0
- phala_cloud-0.4.0/src/phala_cloud/logs.py +540 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/models/__init__.py +20 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/models/auth.py +10 -0
- phala_cloud-0.4.0/src/phala_cloud/models/base.py +35 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/models/cvms.py +147 -11
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/models/nodes.py +17 -1
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/result.py +3 -3
- phala_cloud-0.4.0/src/phala_cloud/user_agent.py +23 -0
- phala_cloud-0.4.0/src/phala_cloud/utils.py +443 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_action_matrix_async.py +6 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_action_matrix_sync.py +5 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_actions_module.py +0 -4
- phala_cloud-0.4.0/tests/test_auth_config.py +151 -0
- phala_cloud-0.4.0/tests/test_commit_cvm_update.py +61 -0
- phala_cloud-0.4.0/tests/test_compose_hash_dump_dict.py +129 -0
- phala_cloud-0.4.0/tests/test_compose_hash_vectors.py +22 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_create_app_instance.py +4 -3
- phala_cloud-0.4.0/tests/test_cvm_config_endpoints.py +157 -0
- phala_cloud-0.4.0/tests/test_cvm_create_config_fields.py +95 -0
- phala_cloud-0.4.0/tests/test_cvm_creation_node.py +113 -0
- phala_cloud-0.4.0/tests/test_cvm_log_urls.py +41 -0
- phala_cloud-0.4.0/tests/test_cvm_ssh_keys.py +90 -0
- phala_cloud-0.4.0/tests/test_cvm_update_contract.py +275 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_e2e_all_interfaces.py +6 -2
- phala_cloud-0.4.0/tests/test_encrypt_env_vars.py +42 -0
- phala_cloud-0.4.0/tests/test_js_parity_schemas.py +173 -0
- phala_cloud-0.4.0/tests/test_logs.py +184 -0
- phala_cloud-0.4.0/tests/test_mr_config_id.py +377 -0
- phala_cloud-0.4.0/tests/test_node_placement.py +118 -0
- phala_cloud-0.4.0/tests/test_prelaunch_script_upgrade.py +145 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_provision_compose_update.py +12 -0
- phala_cloud-0.4.0/tests/test_redirect_security.py +216 -0
- phala_cloud-0.4.0/tests/test_replicate_cvm.py +56 -0
- phala_cloud-0.4.0/tests/test_revoke_current_api_token.py +33 -0
- phala_cloud-0.4.0/tests/test_safe_result.py +14 -0
- phala_cloud-0.4.0/tests/test_unsupported_blockchain_actions.py +13 -0
- phala_cloud-0.4.0/tests/test_update_cvm_resources.py +49 -0
- phala_cloud-0.4.0/tests/test_user_agent.py +69 -0
- phala_cloud-0.4.0/tests/test_watch_delay.py +41 -0
- phala_cloud-0.4.0/tests/test_watch_errors.py +206 -0
- phala_cloud-0.4.0/tests/test_watch_reconnect.py +201 -0
- phala_cloud-0.4.0/tests/test_watch_retry_options.py +47 -0
- phala_cloud-0.4.0/tests/test_with_version.py +49 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/uv.lock +133 -79
- phala_cloud-0.2.0/CHANGELOG.md +0 -2
- phala_cloud-0.2.0/PKG-INFO +0 -165
- phala_cloud-0.2.0/README.md +0 -134
- phala_cloud-0.2.0/pdm.lock +0 -1093
- phala_cloud-0.2.0/src/phala_cloud/__init__.py +0 -65
- phala_cloud-0.2.0/src/phala_cloud/blockchains.py +0 -32
- phala_cloud-0.2.0/src/phala_cloud/models/base.py +0 -18
- phala_cloud-0.2.0/src/phala_cloud/utils.py +0 -133
- phala_cloud-0.2.0/tests/test_mr_config_id.py +0 -125
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/.gitignore +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/.pdm-python +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/.python-version +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/Makefile +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/examples/repl.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/error_codes.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/errors.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/models/apps.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/models/kms.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/models/os_images.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/src/phala_cloud/webhook.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_465_structured_error.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_client_async.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_client_sync.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_cvm_hashid_version_contract.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_cvm_kms_info_chain.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_kms_contract.py +0 -0
- {phala_cloud-0.2.0 → phala_cloud-0.4.0}/tests/test_webhook.py +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
## [0.3.0](https://github.com/Phala-Network/phala-cloud/compare/python-v0.2.0...python-v0.3.0) (2026-11-07)
|
|
2
|
+
|
|
3
|
+
### ⚠ BREAKING CHANGE
|
|
4
|
+
|
|
5
|
+
* **python:** Python: update_cvm_visibility returns {message, correlation_id, status} instead of the CVM record.
|
|
6
|
+
* **python:** SDK requests reject cross-origin URLs. With cookie auth off, combined API-key and Authorization headers are rejected. When SDK API-key or bearer authentication is selected, HTTPX client or request auth and credentials in the request or HTTPX base URL are also rejected. Cookie mode retains caller-supplied authentication.
|
|
7
|
+
* **python:** encrypt_env_vars now returns a string synchronously; use async_encrypt_env_vars for awaited calls. The nonfunctional add_compose_hash and deploy_app_auth wrappers and their safe and functional forms are removed. Watch retry exhaustion raises RequestError instead of TimeoutError, and watch HTTP errors use SDK ApiError subclasses instead of httpx.HTTPStatusError. A raw state followed by EOF is no longer returned as success; only a complete event succeeds. Timeout events, incomplete streams, and transient network failures reconnect within max_retries, while HTTP failures and certificate validation errors are terminal. Cross-origin requests and conflicting authentication are rejected.
|
|
8
|
+
* **sdk:** DeviceIdEntry.os_image_ids (python) and
|
|
9
|
+
DeviceIDEntry.OSImageIDs (go) are removed. No caller in this repo referenced
|
|
10
|
+
either; consumers reading them were reading an empty list.
|
|
11
|
+
|
|
12
|
+
### docs
|
|
13
|
+
|
|
14
|
+
* **python:** clarify authentication migration limits ([9bfe358](https://github.com/Phala-Network/phala-cloud/commit/9bfe3586c498d38caf65904b19d8e09474f52077))
|
|
15
|
+
* **python:** clarify credential precedence ([fd0174d](https://github.com/Phala-Network/phala-cloud/commit/fd0174d59fc125204c6fc5e4d90dc8fee4ea39cb))
|
|
16
|
+
* **python:** describe the compose patch, launch token and compose-hash OS version ([0bee5cb](https://github.com/Phala-Network/phala-cloud/commit/0bee5cb31bd87e9d53ce6f72e5b6e1497223cf3d))
|
|
17
|
+
* **python:** document parity migration ([c828281](https://github.com/Phala-Network/phala-cloud/commit/c828281f8a39c309e2461ae633badd743e292bf8))
|
|
18
|
+
* **python:** note the compose-hash normalization change in the upgrade notes ([8da9947](https://github.com/Phala-Network/phala-cloud/commit/8da9947b6b31bb18484252ed7b82b62605692f9d))
|
|
19
|
+
* **python:** record CVM update contract changes in the upgrade notes ([151a57c](https://github.com/Phala-Network/phala-cloud/commit/151a57c9a8f6f5e43c95933ad9aff681d6107ad1))
|
|
20
|
+
* **sdk:** describe the credits fields of the current user ([cbb3501](https://github.com/Phala-Network/phala-cloud/commit/cbb35011c1018fa7856c3f6af0994dc407a31a81))
|
|
21
|
+
* **sdk:** say what a suspended workspace means for its CVMs ([5694677](https://github.com/Phala-Network/phala-cloud/commit/56946773738a50828f29110dbbba880e2072ff08))
|
|
22
|
+
|
|
23
|
+
### feat
|
|
24
|
+
|
|
25
|
+
* **python:** accept bash_script in the PATCH compose model ([f5c46f4](https://github.com/Phala-Network/phala-cloud/commit/f5c46f4c37a2d290d72235d9b94661623ebe1174))
|
|
26
|
+
* **python:** add CVM annotations, app launch token and init-scripts actions ([55fc51f](https://github.com/Phala-Network/phala-cloud/commit/55fc51f00b53228fe25f0161fb6f0572ef49ca2c))
|
|
27
|
+
* **python:** commit prepared CVM updates ([8dc78f7](https://github.com/Phala-Network/phala-cloud/commit/8dc78f7ca83c47937eaeaec08050de832083a0eb))
|
|
28
|
+
* **python:** manage CVM authorized SSH keys ([226d9cb](https://github.com/Phala-Network/phala-cloud/commit/226d9cb76b3fee131cf18656fd878315c82a2648))
|
|
29
|
+
* **python:** revoke the current API token ([897d410](https://github.com/Phala-Network/phala-cloud/commit/897d410899f32b60f71f25d59e06d0e3231efaa3))
|
|
30
|
+
* **python:** same-path two-phase CVM create on POST /cvms ([4d83996](https://github.com/Phala-Network/phala-cloud/commit/4d83996bcd79fb6f7aa4b92ebeebe5a0dadddcef))
|
|
31
|
+
* **python:** send the compose merge patch, init_scripts and confirm_data_wipe from patch_cvm ([377dddd](https://github.com/Phala-Network/phala-cloud/commit/377dddd2a785dd777050d7bc16bb123485765ed5))
|
|
32
|
+
* **python:** support OIDC and workspace configuration ([71ef5bb](https://github.com/Phala-Network/phala-cloud/commit/71ef5bb8cd1bc5c0e7d2c76de387ad96261200a7))
|
|
33
|
+
* **python:** type available OS images response with requires_gpu ([10240a9](https://github.com/Phala-Network/phala-cloud/commit/10240a9f6daea72e4befe30bd93f929ccaa7fe94))
|
|
34
|
+
* **python:** type the create fields for init scripts, launch token, annotations, raw compose ([00e6689](https://github.com/Phala-Network/phala-cloud/commit/00e66899048bcf993ca75067d93388d1613a4514))
|
|
35
|
+
* **sdk:** add disk usage fields to CVM resource usage ([7274d17](https://github.com/Phala-Network/phala-cloud/commit/7274d17d22f062e660cc0a669eecd614969deb5b))
|
|
36
|
+
* **sdk:** add managed_env to CVM detail schemas ([17ff65c](https://github.com/Phala-Network/phala-cloud/commit/17ff65c6d4faba2958ef5f211e79fb1d24cea014))
|
|
37
|
+
* **sdk:** add max_placeable_count to ProductGpuAvailability (R2-1) ([78d9c7d](https://github.com/Phala-Network/phala-cloud/commit/78d9c7d048bbddcff5ee27b0f4caf66b5a2c145c))
|
|
38
|
+
* **sdk:** add mr_config_id V3 helpers across JS, Python and Go ([e7d2f3a](https://github.com/Phala-Network/phala-cloud/commit/e7d2f3adc479b6a377d3b4efa405574fc00b58e2))
|
|
39
|
+
* **sdk:** add pre-launch script upgrade actions ([992e13d](https://github.com/Phala-Network/phala-cloud/commit/992e13d27dad1d1fff2f5f411f5f915b1a47d73b))
|
|
40
|
+
* **sdk:** align the default request timeout at 60s ([db83998](https://github.com/Phala-Network/phala-cloud/commit/db8399813df52803c0c36b2d00a204d58436cc37))
|
|
41
|
+
* **sdk:** carry GPU product requirement and product-scoped availability ([100dd56](https://github.com/Phala-Network/phala-cloud/commit/100dd5617ac70ba22f91e375752896e40946cac5))
|
|
42
|
+
* **sdk:** declare the full workspace response schema ([12e5e40](https://github.com/Phala-Network/phala-cloud/commit/12e5e4059a7084dfb19e3c0a103ea04fe1fec60a))
|
|
43
|
+
* **sdk:** expose compose_unchanged on compose file update provisioning ([234dd77](https://github.com/Phala-Network/phala-cloud/commit/234dd773c62a3a06932a90c98d6d9aa4ad4ff682))
|
|
44
|
+
* **sdk:** expose unified OS image hardware support ([8e61cc8](https://github.com/Phala-Network/phala-cloud/commit/8e61cc8938c4eddef15f8abd052d838f3a026779))
|
|
45
|
+
* **sdks:** expose GPU rental renewal state ([b0f474b](https://github.com/Phala-Network/phala-cloud/commit/b0f474b3a742ee19d2d90188a9275385303a5d19))
|
|
46
|
+
* **sdk:** support replica OS image selection ([277bb2b](https://github.com/Phala-Network/phala-cloud/commit/277bb2ba649a2615fc0a0b1ae9de00cbaabe6bf8))
|
|
47
|
+
* select creation nodes by physical name ([51be05b](https://github.com/Phala-Network/phala-cloud/commit/51be05b12d18cb3205ea5801d17f530f3f9f2df9))
|
|
48
|
+
* use node names for replicas and allowance checks ([a8009eb](https://github.com/Phala-Network/phala-cloud/commit/a8009ebafbc1c75ac57ce9bf972fb637d00432e6))
|
|
49
|
+
|
|
50
|
+
### fix
|
|
51
|
+
|
|
52
|
+
* prevent API key leaks across SDK redirects ([e3dbb83](https://github.com/Phala-Network/phala-cloud/commit/e3dbb834a7cc85ba031894df663e660b9ec0d815))
|
|
53
|
+
* **python:** accept snake case watch retry options ([8f61974](https://github.com/Phala-Network/phala-cloud/commit/8f61974c69c465969c77807a1ef6afcc701e6757))
|
|
54
|
+
* **python:** align patch_cvm with the PATCH /cvms/{id} request ([59f0183](https://github.com/Phala-Network/phala-cloud/commit/59f018372c8070c8a863d2553ec1ef0fb18d6336))
|
|
55
|
+
* **python:** continue watching after transient SSE errors ([3f2763e](https://github.com/Phala-Network/phala-cloud/commit/3f2763e433f5eb9d910b3e23ab486a232ef23b0c))
|
|
56
|
+
* **python:** drop credential conflict guards ([33c1876](https://github.com/Phala-Network/phala-cloud/commit/33c187655d9d01fea2cf124830406e42446b1541))
|
|
57
|
+
* **python:** hash app-compose like the backend dump_dict ([74b92f4](https://github.com/Phala-Network/phala-cloud/commit/74b92f47771e095ce8207c22e8f11d18fb7c6f39))
|
|
58
|
+
* **python:** hash app-compose with the backend's normalization ([434c9fd](https://github.com/Phala-Network/phala-cloud/commit/434c9fd845aef60641bcd0f0f488d17e35a0be4f))
|
|
59
|
+
* **python:** keep a boolean compose event_log_version from passing as 1 ([fb6c509](https://github.com/Phala-Network/phala-cloud/commit/fb6c509864ca2f80783d904c22be7f5cb097ba12))
|
|
60
|
+
* **python:** make watch errors and retries predictable ([0e09be4](https://github.com/Phala-Network/phala-cloud/commit/0e09be4154509579b3c81f6e028330a2ca9bbc21))
|
|
61
|
+
* **python:** move update_cvm_visibility to the unified PATCH endpoint ([3ae54d4](https://github.com/Phala-Network/phala-cloud/commit/3ae54d494791132ad29694e72594788130695440))
|
|
62
|
+
* **python:** preserve client behavior across versions ([08a83f3](https://github.com/Phala-Network/phala-cloud/commit/08a83f3bbf240311ffe97c5614e4a48baf8806ff))
|
|
63
|
+
* **python:** prevent cross-origin and conflicting credentials ([7586807](https://github.com/Phala-Network/phala-cloud/commit/758680716735e526e7b77065383fc5cbd4fd255a))
|
|
64
|
+
* **python:** provide sync and async env encryption ([6994171](https://github.com/Phala-Network/phala-cloud/commit/69941718535181bb794f9428ed581225e87f2885))
|
|
65
|
+
* **python:** reject conflicting HTTPX authentication ([cc1c094](https://github.com/Phala-Network/phala-cloud/commit/cc1c0941ae2c397eed3e574c0f2c5236027afca8))
|
|
66
|
+
* **python:** reject credentials in injected base URLs ([12f7456](https://github.com/Phala-Network/phala-cloud/commit/12f74560fe37ddbf67acd7f3187b468981ee14f8))
|
|
67
|
+
* **python:** remove unsupported blockchain wrappers ([dec3601](https://github.com/Phala-Network/phala-cloud/commit/dec3601df1d2469e47d77f057b1ece74d3c88436))
|
|
68
|
+
* **python:** replace obsolete Keccak dependency ([c425283](https://github.com/Phala-Network/phala-cloud/commit/c425283c2953796c3bc595ea14fcba0324ad12df))
|
|
69
|
+
* **python:** require certifi 2026.10.19 to drop emSign roots ([06c25c6](https://github.com/Phala-Network/phala-cloud/commit/06c25c6c3768f73f677985c2f8c26cc2c9e03aee))
|
|
70
|
+
* **python:** require complete event to finish watch ([0ac3c2b](https://github.com/Phala-Network/phala-cloud/commit/0ac3c2bbed52902b0bc1fa0abf17a902a4c2edbe))
|
|
71
|
+
* **python:** require the target status on watch complete events ([f8c2a94](https://github.com/Phala-Network/phala-cloud/commit/f8c2a94caf793ea587760eacadefaea8bd0e7677))
|
|
72
|
+
* **python:** retry interrupted watch streams safely ([edeb1fc](https://github.com/Phala-Network/phala-cloud/commit/edeb1fcbfffd9f790205fafca579751919f1ebaf))
|
|
73
|
+
* **python:** return empty app_id when the 465 payload has none ([283a362](https://github.com/Phala-Network/phala-cloud/commit/283a3621f22d8c560578d9bca1dba5871e6f3002))
|
|
74
|
+
* **python:** stop sending allow_restart from update_cvm_resources ([d983378](https://github.com/Phala-Network/phala-cloud/commit/d983378126f6ef9a76d3ba750fcc793e4f6c9547))
|
|
75
|
+
* **python:** unwrap successful empty results ([767c455](https://github.com/Phala-Network/phala-cloud/commit/767c4556202ca72265b9679b0ea4619545cd86da))
|
|
76
|
+
* **sdk:** finish the unified PATCH migration in the async Python client ([2a71dd6](https://github.com/Phala-Network/phala-cloud/commit/2a71dd67a1b604125ff840965ac0a7bc4e2352b9))
|
|
77
|
+
* **sdk:** stop pinning the pubkey request to the node-keyed API ([c29470b](https://github.com/Phala-Network/phala-cloud/commit/c29470b2f7ae46754351f2177a4a5fb6daac5a81))
|
|
78
|
+
|
|
79
|
+
### refactor
|
|
80
|
+
|
|
81
|
+
* **python:** parse 465 hash-registration details in one place ([3476723](https://github.com/Phala-Network/phala-cloud/commit/347672382bce1d1cacb46ecfc44610e27aaf53cb))
|
|
82
|
+
* **sdk:** drop os_image_ids from DeviceIdEntry ([fb69cec](https://github.com/Phala-Network/phala-cloud/commit/fb69cec58a9cda10ad1b4bbd24bc39134a27aafc))
|
|
83
|
+
## [](https://github.com/Phala-Network/phala-cloud/compare/python-v0.1.3...python-v) (2026-07-26)
|
|
84
|
+
|
|
85
|
+
### ⚠ BREAKING CHANGE
|
|
86
|
+
|
|
87
|
+
* **sdk:** reject deprecated user_id/teepod_id/node_id CVM list filters
|
|
88
|
+
|
|
89
|
+
### feat
|
|
90
|
+
|
|
91
|
+
* add algorithm_version to DeviceIdEntry ([701ac00](https://github.com/Phala-Network/phala-cloud/commit/701ac0017acc5fb7851e285e27cc1e9ba7af05cd))
|
|
92
|
+
* add device_ids matrix to node schemas ([de36a3a](https://github.com/Phala-Network/phala-cloud/commit/de36a3af84b1f16abdadeada607d00843817e244))
|
|
93
|
+
* add kms_contract_id to CVM SDK schemas, deprecate kms_id ([16734b9](https://github.com/Phala-Network/phala-cloud/commit/16734b9d22c2e6584c3c320b64d2bd48cdcb5a2b))
|
|
94
|
+
* **go,python:** add mr_config_id computation ([d558b09](https://github.com/Phala-Network/phala-cloud/commit/d558b09cb114300c861ac99d76915779e3363993))
|
|
95
|
+
* **python:** add typed CvmStatus response to get_cvm_status_batch ([01ee3fd](https://github.com/Phala-Network/phala-cloud/commit/01ee3fd2e460700f518278f41cb2ea6b701a61c5))
|
|
96
|
+
* **python:** type app attestation response ([058197b](https://github.com/Phala-Network/phala-cloud/commit/058197ba6940c3fcc0de2d857b4fef3ff562cedc))
|
|
97
|
+
* **sdk/cli:** surface KMS contract verification anchors in on-chain detail ([35a48a3](https://github.com/Phala-Network/phala-cloud/commit/35a48a3a81a4d762cb3a7b49bdcddfb196fd6db1))
|
|
98
|
+
* **sdk:** add hourly_rate, billing_interval, gpu_rental_order to CVM v20260121 ([0f665eb](https://github.com/Phala-Network/phala-cloud/commit/0f665ebaa68158804a835488be4dd76cf1708895))
|
|
99
|
+
* **sdk:** contract-centric KMS API, default to version 2026-06-23 ([0fb89e2](https://github.com/Phala-Network/phala-cloud/commit/0fb89e23c2c7a62bca6ef7f32649d06c9eabf2e4))
|
|
100
|
+
|
|
101
|
+
### fix
|
|
102
|
+
|
|
103
|
+
* **ci:** scope changelog generation to each package's subdirectory ([e2364a8](https://github.com/Phala-Network/phala-cloud/commit/e2364a87872665e5cbc9f62ba0e5ffb15dc04e9b))
|
|
104
|
+
* **cli:** surface request details in API errors ([c53a329](https://github.com/Phala-Network/phala-cloud/commit/c53a329b4cfa3027e05d27c7e3ed5bb8e0fbbfbb))
|
|
105
|
+
* **js:** add version-based schema selection for versioned action responses ([d96f402](https://github.com/Phala-Network/phala-cloud/commit/d96f402353cbbd6557c14908c6d2ba795dab28b7))
|
|
106
|
+
* **python:** lock pysha3 dependency ([e13cc57](https://github.com/Phala-Network/phala-cloud/commit/e13cc57a71699001b0f423361795c0b5084fd00b))
|
|
107
|
+
* **python:** resolve ruff E402 and E501 lint errors ([2b493ce](https://github.com/Phala-Network/phala-cloud/commit/2b493ce2332faeeb9777d57528bf4239ec7d6a8a))
|
|
108
|
+
* **sdk:** expose k256_pubkey on Go and Python CVM KMS info ([b9721b6](https://github.com/Phala-Network/phala-cloud/commit/b9721b6702c93da00370e99b66aa46463a108e53))
|
|
109
|
+
* **sdk:** reject deprecated user_id/teepod_id/node_id CVM list filters ([399cea5](https://github.com/Phala-Network/phala-cloud/commit/399cea5a56054f7566b36ba6f950e4e8eb4bfeef))
|
|
110
|
+
|
|
111
|
+
### refactor
|
|
112
|
+
|
|
113
|
+
* migrate resize endpoint across all SDKs ([56638f1](https://github.com/Phala-Network/phala-cloud/commit/56638f1c1592a1a48dab7fedf9152b60c8e52a01))
|
|
114
|
+
# Changelog
|
|
115
|
+
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: phala-cloud
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Python SDK for Phala Cloud API (sync/async, pydantic, REPL-friendly)
|
|
5
|
+
Project-URL: Homepage, https://github.com/Phala-Network/phala-cloud
|
|
6
|
+
Project-URL: Repository, https://github.com/Phala-Network/phala-cloud
|
|
7
|
+
Project-URL: Issues, https://github.com/Phala-Network/phala-cloud/issues
|
|
8
|
+
Author: Phala Network
|
|
9
|
+
License: Apache-2.0
|
|
10
|
+
Keywords: cloud,cvm,phala,sdk,tee
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: certifi>=2026.10.19
|
|
22
|
+
Requires-Dist: dstack-sdk>=0.5.4
|
|
23
|
+
Requires-Dist: eth-hash[pycryptodome]>=0.8.0
|
|
24
|
+
Requires-Dist: httpx[socks]>=0.27.0
|
|
25
|
+
Requires-Dist: pydantic>=2.7.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.6.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# Phala Cloud Python SDK
|
|
34
|
+
|
|
35
|
+
Python SDK for Phala Cloud API, aligned with `@phala/cloud` action surface.
|
|
36
|
+
|
|
37
|
+
## Goals
|
|
38
|
+
|
|
39
|
+
- Pythonic API (`snake_case`, sync-first REPL experience)
|
|
40
|
+
- Sync + Async parity
|
|
41
|
+
- Pydantic request/response validation
|
|
42
|
+
- Safe calls (`safe_*`) without exceptions
|
|
43
|
+
|
|
44
|
+
## Requirements
|
|
45
|
+
|
|
46
|
+
- Python >= 3.10
|
|
47
|
+
- [uv](https://docs.astral.sh/uv/) (for development)
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install phala-cloud
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quickstart
|
|
56
|
+
|
|
57
|
+
### Sync
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from phala_cloud import create_client
|
|
61
|
+
|
|
62
|
+
client = create_client(api_key="<api-key>")
|
|
63
|
+
me = client.get_current_user()
|
|
64
|
+
print(me.model_dump())
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Async
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import asyncio
|
|
71
|
+
from phala_cloud import create_async_client
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
async def main() -> None:
|
|
75
|
+
client = create_async_client(api_key="<api-key>")
|
|
76
|
+
me = await client.get_current_user()
|
|
77
|
+
print(me.model_dump())
|
|
78
|
+
await client.aclose()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
asyncio.run(main())
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Configuration
|
|
85
|
+
|
|
86
|
+
### Environment variables
|
|
87
|
+
|
|
88
|
+
- `PHALA_CLOUD_API_KEY`
|
|
89
|
+
- `PHALA_OIDC_TOKEN`
|
|
90
|
+
- `PHALA_CLOUD_WORKSPACE`
|
|
91
|
+
- `PHALA_CLOUD_API_PREFIX` (e.g. `https://cloud-api.phala.com/api/v1`)
|
|
92
|
+
|
|
93
|
+
### Client options
|
|
94
|
+
|
|
95
|
+
- `api_key`
|
|
96
|
+
- `bearer_token`
|
|
97
|
+
- `workspace`
|
|
98
|
+
- `base_url`
|
|
99
|
+
- `version` (`2025-10-28` / `2026-01-21` / `2026-05-22`)
|
|
100
|
+
- `timeout`
|
|
101
|
+
- `headers`
|
|
102
|
+
- `use_cookie_auth`
|
|
103
|
+
|
|
104
|
+
The SDK sets `User-Agent` to `phala-cloud-sdk-python/<version> python/<x.y.z> httpx/<ver>`. A `User-Agent` in `headers` replaces that default.
|
|
105
|
+
|
|
106
|
+
A non-empty client option takes precedence over its corresponding environment variable. After resolving both credentials, the SDK uses the API key if both are set. This includes an API key from `PHALA_CLOUD_API_KEY` when `bearer_token` is set explicitly. Cookie auth suppresses both generated authentication headers; it does not remove headers supplied by the caller. The SDK removes surrounding whitespace from the workspace value.
|
|
107
|
+
|
|
108
|
+
When you supply `http_client`, its base URL and timeout control requests; configure them on that client. Watch streams use their own read timeout, as described below. The SDK does not close the supplied client.
|
|
109
|
+
|
|
110
|
+
## Does the SDK follow redirects?
|
|
111
|
+
|
|
112
|
+
No. Redirects can send your API key to another server, so the SDK stops at the first response. This applies to API calls and SSE streams. Set `base_url` to the final API URL instead of relying on a redirect.
|
|
113
|
+
|
|
114
|
+
Direct calls raise `ApiError` for 3xx responses. `request_full` returns the original status, headers, and body with `ok=False`, so you can inspect the response without following it.
|
|
115
|
+
|
|
116
|
+
The SDK ignores `follow_redirects=True` on SDK requests, including requests made with a supplied `http_client`. It does not change that client's settings or close the supplied client. Custom transports must not follow redirects internally.
|
|
117
|
+
|
|
118
|
+
## API Style
|
|
119
|
+
|
|
120
|
+
- Direct methods: raise on HTTP/validation errors
|
|
121
|
+
- Safe methods (`safe_*`): return `SafeResult`
|
|
122
|
+
- Function-style wrappers available in `phala_cloud.actions`
|
|
123
|
+
|
|
124
|
+
Example:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
result = client.safe_get_kms_list()
|
|
128
|
+
if result.ok:
|
|
129
|
+
print(result.data.items)
|
|
130
|
+
else:
|
|
131
|
+
print(result.error)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## How do I commit a prepared CVM update?
|
|
135
|
+
|
|
136
|
+
Pass the CVM ID and the one-time token to `commit_cvm_update`. `compose_hash` and `transaction_hash` are optional. If you omit the compose hash, the server reads it from the token. If you omit the transaction hash, the server checks whether the compose hash is already allowed on-chain. The server still validates the token and the update.
|
|
137
|
+
|
|
138
|
+
## How do I change a CVM's app compose settings?
|
|
139
|
+
|
|
140
|
+
Send `compose` to `patch_cvm` as a JSON Merge Patch: a set field sets the value, a field set to `None` removes the key, and a field you leave out is unchanged. `requirements` merges per key and cannot change `gpu_policy`. `init_scripts` replaces the CVM's platform init scripts with the given slugs (`docker_cleanup`, `env_merge`); `get_cvm_init_scripts` shows which ones the CVM runs and which it can select. Turning on `docker_cleanup` or `requirements.ephemeral_data_disk` erases data on every boot, so it also needs `confirm_data_wipe=True`.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
client.patch_cvm({
|
|
144
|
+
"id": "my-cvm",
|
|
145
|
+
"compose": {"secure_time": True, "swap_size": None, "requirements": {"health_check": True}},
|
|
146
|
+
})
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## How do I gate a CVM with a launch token?
|
|
150
|
+
|
|
151
|
+
On create, send `launch_token` (at least 32 bytes) or `generate_launch_token=True`; the commit response carries a newly issued token once. To rotate, call `set_app_launch_token` (omit `launch_token` to have Phala Cloud generate one), then set each CVM's `compose.requirements.launch_token_hash` to the returned hash before it restarts. `clear_app_launch_token` removes the token after every CVM has dropped the hash. `get_cvm_user_config` returns the token to members who can read the CVM. Phala Cloud and the node operator can read the token, so it protects only against parties who know the public compose.
|
|
152
|
+
|
|
153
|
+
## How do I compute a compose hash locally?
|
|
154
|
+
|
|
155
|
+
`get_compose_hash(compose, os_image_version="0.6.0")` hashes the compose the way Phala Cloud does for that OS image: below 0.6.0 `manifest_version` is 2 and `init_script` is a single string, from 0.6.0 they are `"3"` and a list. Without `os_image_version` both fields are hashed as given.
|
|
156
|
+
|
|
157
|
+
## How does watching a CVM retry?
|
|
158
|
+
|
|
159
|
+
`watch_cvm_state` reconnects after a server timeout event, an incomplete stream, or a transient network failure. Set `max_retries` to limit reconnects; the default is unlimited. Set `retry_delay` in seconds (default 5). The aliases `maxRetries` and `retryDelay` also work. The stream read timeout is the requested `timeout` plus `interval` plus 5 seconds.
|
|
160
|
+
|
|
161
|
+
Only a complete event finishes the watch. The server may send an error event and then continue streaming. If retries are exhausted, the SDK raises `RequestError` with the last available server and network error details. HTTP errors use the same SDK exception types as other requests and are not retried. In async code, cancelling the task closes the stream and propagates cancellation. Previous versions raised `TimeoutError` on retry exhaustion; catch `RequestError` instead.
|
|
162
|
+
|
|
163
|
+
## Are blockchain actions supported?
|
|
164
|
+
|
|
165
|
+
The Python SDK no longer exposes `add_compose_hash`, `deploy_app_auth`, or their safe wrappers. These wrappers did not implement the blockchain operations. Use the JavaScript SDK for these operations instead.
|
|
166
|
+
|
|
167
|
+
## How do I encrypt environment variables?
|
|
168
|
+
|
|
169
|
+
Pass the output of `parse_env_vars` or `dstack_sdk.EnvVar` objects to `encrypt_env_vars(envs, public_key_hex)`. It returns the encrypted string synchronously. In async code, use `await async_encrypt_env_vars(envs, public_key_hex)` instead.
|
|
170
|
+
|
|
171
|
+
This changes the previous `encrypt_env_vars` behavior: code that awaited it must switch to `async_encrypt_env_vars`.
|
|
172
|
+
|
|
173
|
+
## How do I upgrade to these SDK changes?
|
|
174
|
+
|
|
175
|
+
- Replace `await encrypt_env_vars(...)` with `await async_encrypt_env_vars(...)`. The `encrypt_env_vars` function now returns a string synchronously.
|
|
176
|
+
- Use the JavaScript SDK for `add_compose_hash` and `deploy_app_auth`. Their Python wrappers have been removed.
|
|
177
|
+
- Catch `RequestError` instead of `TimeoutError` when watch retries are exhausted. Watch HTTP errors now use SDK exceptions instead of `httpx.HTTPStatusError`.
|
|
178
|
+
- Do not rely on a raw state event followed by a closed stream as a successful watch result. Only a complete event finishes the watch. Timeouts, incomplete streams, and transient network failures use the reconnect budget.
|
|
179
|
+
- `patch_cvm` validates `gpus` as `{"gpus": [{"slot": ..., "product_id": ...}], "attach_mode": ...}`, the shape the API accepts. Other shapes now fail validation instead of being sent and ignored. `patch_cvm` also accepts `instance_type`, and `prepare_only=True` sends `X-Prepare-Only: true`; the 465 result then includes `commit_token`, `commit_url`, `api_commit_url` and `onchain_status`.
|
|
180
|
+
- `update_cvm_visibility` now calls `PATCH /cvms/{id}` instead of the deprecated `PATCH /cvms/{id}/visibility`. It returns `message`, `correlation_id` and `status` instead of the CVM record; call `get_cvm_info` if you need the record.
|
|
181
|
+
- `update_cvm_resources` no longer sends `allow_restart`, which the API ignores. The field is deprecated.
|
|
182
|
+
- `get_compose_hash` now drops null `storage_discard`, `event_log_version`, `snapshotter` and `verity_volumes` and always emits `tproxy_enabled` (defaulting to `gateway_enabled`), as the API does. A compose without `tproxy_enabled` hashes differently than before.
|
|
183
|
+
|
|
184
|
+
## Development
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
cd python
|
|
188
|
+
|
|
189
|
+
# Install dependencies
|
|
190
|
+
uv sync
|
|
191
|
+
|
|
192
|
+
# Run tests
|
|
193
|
+
make test
|
|
194
|
+
|
|
195
|
+
# Lint & format
|
|
196
|
+
make check
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## E2E Test
|
|
200
|
+
|
|
201
|
+
E2E tests cover sync + async, direct + safe styles, and full interface paths.
|
|
202
|
+
|
|
203
|
+
Required:
|
|
204
|
+
|
|
205
|
+
- `PHALA_CLOUD_E2E_API_KEY` — your Phala Cloud API key
|
|
206
|
+
|
|
207
|
+
Optional:
|
|
208
|
+
|
|
209
|
+
- `PHALA_CLOUD_E2E_BASE_URL` — defaults to `https://cloud-api.phala.com/api/v1`
|
|
210
|
+
|
|
211
|
+
### Run
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cd python
|
|
215
|
+
PHALA_CLOUD_E2E_API_KEY="<api-key>" make e2e
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Or put them in `python/.env.test`:
|
|
219
|
+
|
|
220
|
+
```dotenv
|
|
221
|
+
PHALA_CLOUD_E2E_API_KEY=<api-key>
|
|
222
|
+
# PHALA_CLOUD_E2E_BASE_URL=https://cloud-api.phala.com/api/v1
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Then simply:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
cd python
|
|
229
|
+
make e2e
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
Apache-2.0
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Phala Cloud Python SDK
|
|
2
|
+
|
|
3
|
+
Python SDK for Phala Cloud API, aligned with `@phala/cloud` action surface.
|
|
4
|
+
|
|
5
|
+
## Goals
|
|
6
|
+
|
|
7
|
+
- Pythonic API (`snake_case`, sync-first REPL experience)
|
|
8
|
+
- Sync + Async parity
|
|
9
|
+
- Pydantic request/response validation
|
|
10
|
+
- Safe calls (`safe_*`) without exceptions
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
- Python >= 3.10
|
|
15
|
+
- [uv](https://docs.astral.sh/uv/) (for development)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install phala-cloud
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quickstart
|
|
24
|
+
|
|
25
|
+
### Sync
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from phala_cloud import create_client
|
|
29
|
+
|
|
30
|
+
client = create_client(api_key="<api-key>")
|
|
31
|
+
me = client.get_current_user()
|
|
32
|
+
print(me.model_dump())
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Async
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import asyncio
|
|
39
|
+
from phala_cloud import create_async_client
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def main() -> None:
|
|
43
|
+
client = create_async_client(api_key="<api-key>")
|
|
44
|
+
me = await client.get_current_user()
|
|
45
|
+
print(me.model_dump())
|
|
46
|
+
await client.aclose()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
asyncio.run(main())
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
### Environment variables
|
|
55
|
+
|
|
56
|
+
- `PHALA_CLOUD_API_KEY`
|
|
57
|
+
- `PHALA_OIDC_TOKEN`
|
|
58
|
+
- `PHALA_CLOUD_WORKSPACE`
|
|
59
|
+
- `PHALA_CLOUD_API_PREFIX` (e.g. `https://cloud-api.phala.com/api/v1`)
|
|
60
|
+
|
|
61
|
+
### Client options
|
|
62
|
+
|
|
63
|
+
- `api_key`
|
|
64
|
+
- `bearer_token`
|
|
65
|
+
- `workspace`
|
|
66
|
+
- `base_url`
|
|
67
|
+
- `version` (`2025-10-28` / `2026-01-21` / `2026-05-22`)
|
|
68
|
+
- `timeout`
|
|
69
|
+
- `headers`
|
|
70
|
+
- `use_cookie_auth`
|
|
71
|
+
|
|
72
|
+
The SDK sets `User-Agent` to `phala-cloud-sdk-python/<version> python/<x.y.z> httpx/<ver>`. A `User-Agent` in `headers` replaces that default.
|
|
73
|
+
|
|
74
|
+
A non-empty client option takes precedence over its corresponding environment variable. After resolving both credentials, the SDK uses the API key if both are set. This includes an API key from `PHALA_CLOUD_API_KEY` when `bearer_token` is set explicitly. Cookie auth suppresses both generated authentication headers; it does not remove headers supplied by the caller. The SDK removes surrounding whitespace from the workspace value.
|
|
75
|
+
|
|
76
|
+
When you supply `http_client`, its base URL and timeout control requests; configure them on that client. Watch streams use their own read timeout, as described below. The SDK does not close the supplied client.
|
|
77
|
+
|
|
78
|
+
## Does the SDK follow redirects?
|
|
79
|
+
|
|
80
|
+
No. Redirects can send your API key to another server, so the SDK stops at the first response. This applies to API calls and SSE streams. Set `base_url` to the final API URL instead of relying on a redirect.
|
|
81
|
+
|
|
82
|
+
Direct calls raise `ApiError` for 3xx responses. `request_full` returns the original status, headers, and body with `ok=False`, so you can inspect the response without following it.
|
|
83
|
+
|
|
84
|
+
The SDK ignores `follow_redirects=True` on SDK requests, including requests made with a supplied `http_client`. It does not change that client's settings or close the supplied client. Custom transports must not follow redirects internally.
|
|
85
|
+
|
|
86
|
+
## API Style
|
|
87
|
+
|
|
88
|
+
- Direct methods: raise on HTTP/validation errors
|
|
89
|
+
- Safe methods (`safe_*`): return `SafeResult`
|
|
90
|
+
- Function-style wrappers available in `phala_cloud.actions`
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
result = client.safe_get_kms_list()
|
|
96
|
+
if result.ok:
|
|
97
|
+
print(result.data.items)
|
|
98
|
+
else:
|
|
99
|
+
print(result.error)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## How do I commit a prepared CVM update?
|
|
103
|
+
|
|
104
|
+
Pass the CVM ID and the one-time token to `commit_cvm_update`. `compose_hash` and `transaction_hash` are optional. If you omit the compose hash, the server reads it from the token. If you omit the transaction hash, the server checks whether the compose hash is already allowed on-chain. The server still validates the token and the update.
|
|
105
|
+
|
|
106
|
+
## How do I change a CVM's app compose settings?
|
|
107
|
+
|
|
108
|
+
Send `compose` to `patch_cvm` as a JSON Merge Patch: a set field sets the value, a field set to `None` removes the key, and a field you leave out is unchanged. `requirements` merges per key and cannot change `gpu_policy`. `init_scripts` replaces the CVM's platform init scripts with the given slugs (`docker_cleanup`, `env_merge`); `get_cvm_init_scripts` shows which ones the CVM runs and which it can select. Turning on `docker_cleanup` or `requirements.ephemeral_data_disk` erases data on every boot, so it also needs `confirm_data_wipe=True`.
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
client.patch_cvm({
|
|
112
|
+
"id": "my-cvm",
|
|
113
|
+
"compose": {"secure_time": True, "swap_size": None, "requirements": {"health_check": True}},
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## How do I gate a CVM with a launch token?
|
|
118
|
+
|
|
119
|
+
On create, send `launch_token` (at least 32 bytes) or `generate_launch_token=True`; the commit response carries a newly issued token once. To rotate, call `set_app_launch_token` (omit `launch_token` to have Phala Cloud generate one), then set each CVM's `compose.requirements.launch_token_hash` to the returned hash before it restarts. `clear_app_launch_token` removes the token after every CVM has dropped the hash. `get_cvm_user_config` returns the token to members who can read the CVM. Phala Cloud and the node operator can read the token, so it protects only against parties who know the public compose.
|
|
120
|
+
|
|
121
|
+
## How do I compute a compose hash locally?
|
|
122
|
+
|
|
123
|
+
`get_compose_hash(compose, os_image_version="0.6.0")` hashes the compose the way Phala Cloud does for that OS image: below 0.6.0 `manifest_version` is 2 and `init_script` is a single string, from 0.6.0 they are `"3"` and a list. Without `os_image_version` both fields are hashed as given.
|
|
124
|
+
|
|
125
|
+
## How does watching a CVM retry?
|
|
126
|
+
|
|
127
|
+
`watch_cvm_state` reconnects after a server timeout event, an incomplete stream, or a transient network failure. Set `max_retries` to limit reconnects; the default is unlimited. Set `retry_delay` in seconds (default 5). The aliases `maxRetries` and `retryDelay` also work. The stream read timeout is the requested `timeout` plus `interval` plus 5 seconds.
|
|
128
|
+
|
|
129
|
+
Only a complete event finishes the watch. The server may send an error event and then continue streaming. If retries are exhausted, the SDK raises `RequestError` with the last available server and network error details. HTTP errors use the same SDK exception types as other requests and are not retried. In async code, cancelling the task closes the stream and propagates cancellation. Previous versions raised `TimeoutError` on retry exhaustion; catch `RequestError` instead.
|
|
130
|
+
|
|
131
|
+
## Are blockchain actions supported?
|
|
132
|
+
|
|
133
|
+
The Python SDK no longer exposes `add_compose_hash`, `deploy_app_auth`, or their safe wrappers. These wrappers did not implement the blockchain operations. Use the JavaScript SDK for these operations instead.
|
|
134
|
+
|
|
135
|
+
## How do I encrypt environment variables?
|
|
136
|
+
|
|
137
|
+
Pass the output of `parse_env_vars` or `dstack_sdk.EnvVar` objects to `encrypt_env_vars(envs, public_key_hex)`. It returns the encrypted string synchronously. In async code, use `await async_encrypt_env_vars(envs, public_key_hex)` instead.
|
|
138
|
+
|
|
139
|
+
This changes the previous `encrypt_env_vars` behavior: code that awaited it must switch to `async_encrypt_env_vars`.
|
|
140
|
+
|
|
141
|
+
## How do I upgrade to these SDK changes?
|
|
142
|
+
|
|
143
|
+
- Replace `await encrypt_env_vars(...)` with `await async_encrypt_env_vars(...)`. The `encrypt_env_vars` function now returns a string synchronously.
|
|
144
|
+
- Use the JavaScript SDK for `add_compose_hash` and `deploy_app_auth`. Their Python wrappers have been removed.
|
|
145
|
+
- Catch `RequestError` instead of `TimeoutError` when watch retries are exhausted. Watch HTTP errors now use SDK exceptions instead of `httpx.HTTPStatusError`.
|
|
146
|
+
- Do not rely on a raw state event followed by a closed stream as a successful watch result. Only a complete event finishes the watch. Timeouts, incomplete streams, and transient network failures use the reconnect budget.
|
|
147
|
+
- `patch_cvm` validates `gpus` as `{"gpus": [{"slot": ..., "product_id": ...}], "attach_mode": ...}`, the shape the API accepts. Other shapes now fail validation instead of being sent and ignored. `patch_cvm` also accepts `instance_type`, and `prepare_only=True` sends `X-Prepare-Only: true`; the 465 result then includes `commit_token`, `commit_url`, `api_commit_url` and `onchain_status`.
|
|
148
|
+
- `update_cvm_visibility` now calls `PATCH /cvms/{id}` instead of the deprecated `PATCH /cvms/{id}/visibility`. It returns `message`, `correlation_id` and `status` instead of the CVM record; call `get_cvm_info` if you need the record.
|
|
149
|
+
- `update_cvm_resources` no longer sends `allow_restart`, which the API ignores. The field is deprecated.
|
|
150
|
+
- `get_compose_hash` now drops null `storage_discard`, `event_log_version`, `snapshotter` and `verity_volumes` and always emits `tproxy_enabled` (defaulting to `gateway_enabled`), as the API does. A compose without `tproxy_enabled` hashes differently than before.
|
|
151
|
+
|
|
152
|
+
## Development
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
cd python
|
|
156
|
+
|
|
157
|
+
# Install dependencies
|
|
158
|
+
uv sync
|
|
159
|
+
|
|
160
|
+
# Run tests
|
|
161
|
+
make test
|
|
162
|
+
|
|
163
|
+
# Lint & format
|
|
164
|
+
make check
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## E2E Test
|
|
168
|
+
|
|
169
|
+
E2E tests cover sync + async, direct + safe styles, and full interface paths.
|
|
170
|
+
|
|
171
|
+
Required:
|
|
172
|
+
|
|
173
|
+
- `PHALA_CLOUD_E2E_API_KEY` — your Phala Cloud API key
|
|
174
|
+
|
|
175
|
+
Optional:
|
|
176
|
+
|
|
177
|
+
- `PHALA_CLOUD_E2E_BASE_URL` — defaults to `https://cloud-api.phala.com/api/v1`
|
|
178
|
+
|
|
179
|
+
### Run
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
cd python
|
|
183
|
+
PHALA_CLOUD_E2E_API_KEY="<api-key>" make e2e
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Or put them in `python/.env.test`:
|
|
187
|
+
|
|
188
|
+
```dotenv
|
|
189
|
+
PHALA_CLOUD_E2E_API_KEY=<api-key>
|
|
190
|
+
# PHALA_CLOUD_E2E_BASE_URL=https://cloud-api.phala.com/api/v1
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Then simply:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
cd python
|
|
197
|
+
make e2e
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
Apache-2.0
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "phala-cloud"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Python SDK for Phala Cloud API (sync/async, pydantic, REPL-friendly)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -24,9 +24,11 @@ classifiers = [
|
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
26
|
"httpx[socks]>=0.27.0",
|
|
27
|
+
# 2026.10.19 removes emSign ECC Root CA - G3 (compromised eMudhra intermediates).
|
|
28
|
+
"certifi>=2026.10.19",
|
|
27
29
|
"pydantic>=2.7.0",
|
|
28
30
|
"dstack-sdk>=0.5.4",
|
|
29
|
-
"
|
|
31
|
+
"eth-hash[pycryptodome]>=0.8.0",
|
|
30
32
|
]
|
|
31
33
|
|
|
32
34
|
[project.optional-dependencies]
|