{"id":51794287,"url":"https://github.com/valkyoth/cloud-sdk","last_synced_at":"2026-07-21T01:42:19.068Z","repository":{"id":370166696,"uuid":"1293494355","full_name":"valkyoth/cloud-sdk","owner":"valkyoth","description":"Multi-provider cloud SDK for Rust with a security-gated release process.","archived":false,"fork":false,"pushed_at":"2026-07-15T12:54:42.000Z","size":2405,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-15T13:10:05.745Z","etag":null,"topics":["api-client","cloud","cloud-sdk","devops","dns","hacktoberfest","hetzner","infrastructure","rust","sdk","security","supply-chain"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/cloud-sdk","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/valkyoth.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["eldryoth"],"thanks_dev":"u/gh/eldryoth"}},"created_at":"2026-07-08T11:13:41.000Z","updated_at":"2026-07-15T12:55:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/valkyoth/cloud-sdk","commit_stats":null,"previous_names":["valkyoth/cloud-sdk"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/valkyoth/cloud-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valkyoth%2Fcloud-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valkyoth%2Fcloud-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valkyoth%2Fcloud-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valkyoth%2Fcloud-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valkyoth","download_url":"https://codeload.github.com/valkyoth/cloud-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valkyoth%2Fcloud-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35705774,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"ssl_error","status_checked_at":"2026-07-20T02:08:09.736Z","response_time":111,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","cloud","cloud-sdk","devops","dns","hacktoberfest","hetzner","infrastructure","rust","sdk","security","supply-chain"],"created_at":"2026-07-21T01:42:14.543Z","updated_at":"2026-07-21T01:42:19.049Z","avatar_url":"https://github.com/valkyoth.png","language":"Rust","funding_links":["https://github.com/sponsors/eldryoth","https://thanks.dev/u/gh/eldryoth"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cb\u003eno_std-first provider-neutral cloud SDK foundation for Rust.\u003c/b\u003e\u003cbr\u003e\n  Provider crates, explicit API domains, security-first release gates, and transport-free core types.\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://crates.io/crates/cloud-sdk\"\u003eCrates.io\u003c/a\u003e\n  |\n  \u003ca href=\"https://docs.rs/cloud-sdk\"\u003eDocs.rs\u003c/a\u003e\n  |\n  \u003ca href=\"https://github.com/valkyoth/cloud-sdk/blob/main/docs/RELEASE_PLAN.md\"\u003eRelease Plan\u003c/a\u003e\n  |\n  \u003ca href=\"https://github.com/valkyoth/cloud-sdk/blob/main/docs/PLATFORM_SUPPORT.md\"\u003ePlatforms\u003c/a\u003e\n  |\n  \u003ca href=\"https://github.com/valkyoth/cloud-sdk/blob/main/docs/threat-model.md\"\u003eThreat Model\u003c/a\u003e\n  |\n  \u003ca href=\"https://github.com/valkyoth/cloud-sdk/blob/main/SECURITY.md\"\u003eSecurity\u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/valkyoth/cloud-sdk\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/valkyoth/cloud-sdk/main/.github/images/cloud-sdk.webp\" alt=\"cloud-sdk Rust crate overview\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# cloud-sdk\n\n`cloud-sdk` is a `no_std`-first Rust foundation for building secure, portable\nSDKs for cloud services. Provider APIs use shared, provider-neutral contracts\nwhile retaining ownership of their request models, response models, endpoint\nrules, and errors.\n\nThe workspace keeps networking, TLS, async runtimes, serialization,\nfilesystem access, clocks, and secret storage outside the default dependency\ngraph. These capabilities are explicit optional boundaries so applications\ncan select the transport, runtime, trust policy, and platform integration that\nfit their environment. The project emphasizes validated inputs, bounded\nmemory use, caller-controlled behavior, cross-platform compatibility,\nsecurity review, and reproducible release evidence.\n\n## Cost And Production Warning\n\nCloud APIs can create, modify, and delete billable resources. This SDK is built\nwith careful review, tests, security gates, and release checks, but no SDK can\nguarantee that it is free from mistakes or that every provider-side API behavior\nis risk-free.\n\nBefore running code against a real cloud account, review the exact operations,\ninputs, permissions, and provider pricing yourself. You are responsible for the\ninfrastructure actions you execute and for any costs, downtime, data loss, or\nconfiguration changes caused by those actions. If you find an SDK mistake,\nplease report it so it can be fixed.\n\n## Current Status\n\nCompleted milestones and upcoming work are tracked in the\n[release roadmap](https://github.com/valkyoth/cloud-sdk/blob/main/docs/RELEASE_PLAN.md).\nPublished and planned versions for each independently versioned crate are\nlisted in the\n[crate version matrix](https://github.com/valkyoth/cloud-sdk/blob/main/docs/CRATE_VERSION_MATRIX.md).\n\nCurrent releases provide provider-neutral contracts and provider-owned,\nvalidated request and response building blocks. Before the high-level client is\nstabilized, the roadmap now hardens extensible provider identities, HTTP\nmetadata, authentication, pagination, local async, bounded decoding, and typed\noperation contracts, then validates them with an unpublished OVHcloud API v2\narchitecture probe, a narrow credential-free Robot wire fixture, and\nfull-fidelity Hetzner vertical slices before the neutral API freeze.\n\n## Trust Dashboard\n\n| Area | Status |\n| --- | --- |\n| License | `MIT OR Apache-2.0` |\n| MSRV | Rust `1.90.0` |\n| Pinned toolchain | Rust `1.97.1` |\n| Default target | `no_std` |\n| Default runtime dependencies | none in `cloud-sdk`; provider crates remain transport-free by default |\n| Unsafe policy | first-party crates use `#![forbid(unsafe_code)]` |\n| Default features | empty |\n| Network defaults | none |\n| Secret storage defaults | none |\n| Release evidence | local gates, dependency policy, SBOM, pentest report before tags |\n| Platform support | explicit tiers and targets in [`docs/PLATFORM_SUPPORT.md`](https://github.com/valkyoth/cloud-sdk/blob/main/docs/PLATFORM_SUPPORT.md) |\n| Crate versions | tracked in [`docs/CRATE_VERSION_MATRIX.md`](https://github.com/valkyoth/cloud-sdk/blob/main/docs/CRATE_VERSION_MATRIX.md) |\n| 1.0 target | serious production-ready foundation plus complete Hetzner Cloud, DNS, Console Storage Box, and Robot provider |\n\n## Provider Roadmap\n\n| Provider or role | Target | Crate or status |\n| --- | --- | --- |\n| [`Hetzner Cloud`](https://www.hetzner.com/) | `1.0.0` | [`cloud-sdk-hetzner`](https://crates.io/crates/cloud-sdk-hetzner) |\n| [`Hetzner Robot`](https://robot.hetzner.com/doc/webservice/en.html) | `1.0.0` | pre-1.0 milestones in `cloud-sdk-hetzner` |\n| [`OVHcloud API v2`](https://docs.ovhcloud.com/en/guides/manage-and-operate/api/apiv2/) architecture probe | `0.57.0 - 0.61.0` | unpublished conformance fixture; neutral freeze follows in `0.62.0` |\n| [`Scaleway`](https://www.scaleway.com/en/developers/api/) | `1.1.0 - 1.6.0` | planned `cloud-sdk-scaleway`; stable GA APIs first |\n| [`DigitalOcean`](https://docs.digitalocean.com/reference/api/reference/public-apis/) | `1.7.0 - 1.12.0` | planned `cloud-sdk-digitalocean` |\n| [`OVHcloud`](https://docs.ovhcloud.com/en/) full provider | later post-1.0 | planned `cloud-sdk-ovhcloud` after a dedicated v1/v2 and product-scope plan |\n\nThe probe exists to test the shared architecture against a materially different\nAPI. Published providers receive their own source lock, threat model, API\nmatrix, release plan, tests, and pentest gates.\n\n## Rust Version Support\n\nThe minimum supported Rust version is Rust `1.90.0`. Development uses the\npinned stable Rust `1.97.1` until the toolchain policy is updated.\n\n| Rust | Local Evidence |\n| --- | --- |\n| `1.90.0 - 1.96.1` | `cargo +\u003cversion\u003e check --workspace --all-features` for every supported compiler |\n| `1.97.0` | `cargo +1.97.0 check --workspace --all-features` |\n| `1.97.1` | `scripts/checks.sh` |\n\nPortable and native platform evidence is documented in\n[`docs/PLATFORM_SUPPORT.md`](https://github.com/valkyoth/cloud-sdk/blob/main/docs/PLATFORM_SUPPORT.md).\n\n## Install\n\n```toml\n[dependencies]\ncloud-sdk = \"0.31.0\"\ncloud-sdk-hetzner = \"0.24.0\"\n```\n\n## cloud-sdk Features\n\n| Feature | Default | Effect |\n| --- | --- | --- |\n| `default` | yes | Empty; keeps the crate allocation-free and `no_std`. |\n| `alloc` | no | Enables APIs that require the Rust `alloc` crate. |\n| `std` | no | Enables `alloc` and standard-library integration. |\n\nDocs.rs builds this crate with all features so every public optional API is\nvisible. Applications should enable only the features they use.\n\n## Guides\n\n- [Provider-neutral quickstart](https://github.com/valkyoth/cloud-sdk/blob/main/docs/QUICKSTART.md)\n- [Hetzner workflow examples](https://github.com/valkyoth/cloud-sdk/blob/main/docs/HETZNER_EXAMPLES.md)\n- [Hetzner live smoke testing](https://github.com/valkyoth/cloud-sdk/blob/main/docs/LIVE_SMOKE_TESTING.md)\n- [Security recipes](https://github.com/valkyoth/cloud-sdk/blob/main/docs/SECURITY_RECIPES.md)\n- [Release runbook](https://github.com/valkyoth/cloud-sdk/blob/main/docs/RELEASE_RUNBOOK.md)\n- [Versioning and error policy](https://github.com/valkyoth/cloud-sdk/blob/main/docs/VERSIONING_POLICY.md)\n- [Migrating to v0.29](https://github.com/valkyoth/cloud-sdk/blob/main/docs/MIGRATION_0.29.0.md)\n- [Migrating to v0.30](https://github.com/valkyoth/cloud-sdk/blob/main/docs/MIGRATION_0.30.0.md)\n- [Migrating to v0.31](https://github.com/valkyoth/cloud-sdk/blob/main/docs/MIGRATION_0.31.0.md)\n- [Deprecated endpoint policy](https://github.com/valkyoth/cloud-sdk/blob/main/docs/DEPRECATED_ENDPOINT_POLICY.md)\n\n## Provider-Neutral Quickstart\n\n```rust\nuse cloud_sdk::Method;\nuse cloud_sdk::transport::{RequestTarget, TransportRequest};\n\nlet Ok(target) = RequestTarget::new(\"/resources?page=1\") else {\n    return;\n};\nlet request = TransportRequest::new(Method::Get, target);\n\nassert_eq!(request.method(), Method::Get);\nassert_eq!(request.target().as_str(), \"/resources?page=1\");\nassert!(request.body().is_empty());\n```\n\nThe core contracts perform no I/O and select no executor. Use\n`cloud-sdk-testkit` for deterministic blocking or async tests, or opt into\n`cloud-sdk-reqwest/blocking-rustls`, `blocking-rustls-webpki-roots`,\n`blocking-rustls-fips`, or `async-rustls` for HTTPS.\n\n### Prepared Request Policy\n\nProvider operations can bind request execution to explicit impact, retry,\ncost, endpoint, and response rules without selecting a transport:\n\n```rust\nuse cloud_sdk::operation::{\n    CostIntent, OperationImpact, OperationMetadata, RequestSemantics,\n    RetryEligibility,\n};\n\n# fn main() -\u003e Result\u003c(), cloud_sdk::operation::OperationMetadataError\u003e {\nlet metadata = OperationMetadata::new(\n    OperationImpact::Mutation,\n    RequestSemantics::Idempotent,\n    RetryEligibility::ExplicitPolicy,\n    CostIntent::MayIncurCost,\n)?;\n\nassert_eq!(metadata.impact(), OperationImpact::Mutation);\nassert_eq!(\n    metadata.retry_eligibility(),\n    RetryEligibility::ExplicitPolicy,\n);\n# Ok(())\n# }\n```\n\n`PrepareOperation` writes a validated target and body into caller-owned\nstorage and returns one `PreparedRequest`. Blocking and async execution verify\nthe immutable endpoint before sending, lend only the response policy's admitted\ncapacity, and return `CheckedResponse` only after status, body, and content type\npass. Prepared transports must implement `ResponseStorageSanitizer`; execution\nclears the complete caller buffer before endpoint checks so a smaller policy\ncannot leave bytes from an earlier larger response in the unused tail. The SDK\nstill performs no automatic retry or scheduling.\n\n## Optional Blocking Transport\n\n```toml\n[dependencies]\ncloud-sdk = \"0.31.0\"\ncloud-sdk-reqwest = { version = \"0.20.2\", features = [\"blocking-rustls\"] }\n```\n\nThe production builder is HTTPS-only, requires explicit bounded timeouts and a\nuser agent, uses rustls with TLS 1.2 minimum, and disables redirects, retries,\nproxies, referer generation, and response decompression. It forces HTTP/1 and\nthe system resolver even if another dependency enables reqwest HTTP/2 or\nHickory DNS. The caller owns token generation, scope, rotation, revocation,\nand cleanup of immutable secret sources. Mutable and guarded token constructors\nclear their complete source buffers. Cloneable clients support caller-bounded\nconcurrency and atomic rotation without holding credential locks across I/O.\n\nSee the complete, compile-checked\n[`cloud-sdk-reqwest` blocking example](https://docs.rs/cloud-sdk-reqwest/latest/cloud_sdk_reqwest/#blocking-example)\nfor client construction and request execution.\n\n### Optional Deterministic Root Snapshot\n\nUse a source-pinned Mozilla root snapshot instead of host trust-store contents\nwhen deterministic public WebPKI roots are required:\n\n```toml\n[dependencies]\ncloud-sdk = \"0.31.0\"\ncloud-sdk-reqwest = { version = \"0.20.2\", features = [\"blocking-rustls-webpki-roots\"] }\n```\n\nThe blocking API is unchanged. This feature excludes host-added enterprise\nroots from trust decisions and updates roots only when `webpki-roots` is\nreviewed and upgraded. It does not provide certificate revocation checking,\ncertificate pinning, private PKI support, or FIPS status. When combined with\n`blocking-rustls-fips`, the explicit FIPS roots-and-CRLs policy wins.\n\n### Optional Blocking FIPS Transport\n\nApplications that require the reviewed FIPS path must select the dedicated\nfeature instead of relying on dependency feature unification:\n\n```toml\n[dependencies]\ncloud-sdk = \"0.31.0\"\ncloud-sdk-reqwest = { version = \"0.20.2\", features = [\"blocking-rustls-fips\"] }\n```\n\nClient construction explicitly selects rustls' AWS-LC FIPS provider and fails\nunless both `CryptoProvider::fips()` and `ClientConfig::fips()` report true. It\nalso requires a `FipsTlsPolicy` with deployment-managed trust roots and\ncomplete, current CRLs; unknown or expired revocation status fails closed. The\nfeature alone does not make an application or deployment FIPS compliant: the\ncaller must satisfy the AWS-LC security policy, approved operating-environment,\nbuild, entropy, deployment, and operational requirements. The full policy\nexample is in the\n[reqwest crate README](https://crates.io/crates/cloud-sdk-reqwest). See also the\n[FIPS dependency admission](https://github.com/valkyoth/cloud-sdk/blob/main/docs/dependency-admission-reqwest-fips.md).\n\n## Optional Async Transport\n\n```toml\n[dependencies]\ncloud-sdk = \"0.31.0\"\ncloud-sdk-reqwest = { version = \"0.20.2\", features = [\"async-rustls\"] }\n```\n\nThe async adapter requires an active Tokio executor because reqwest uses Tokio\ninternally; the core trait and testkit remain executor-neutral. Responses are\nbuffered only up to caller capacity and copied after complete success. Timeout,\nread failure, overflow, or cancellation leaves the caller buffer cleared.\nThe shared-reference contract does not spawn tasks or select a concurrency\nlimit; callers own task lifetimes, bounds, cancellation, and executor policy.\nSee the complete, compile-checked\n[`cloud-sdk-reqwest` async example](https://docs.rs/cloud-sdk-reqwest/latest/cloud_sdk_reqwest/#async-example)\nfor client construction and request execution.\n\n## Pagination Cursor Example\n\n```rust\nuse cloud_sdk::pagination::{\n    PageLimit, PageMetadata, PageNumber, PaginationCursor,\n};\n\n# fn main() -\u003e Result\u003c(), cloud_sdk::pagination::PaginationError\u003e {\nlet first = PageNumber::new(1)?;\nlet second = PageNumber::new(2)?;\nlet limit = PageLimit::new(10)?;\nlet mut cursor = PaginationCursor::new(first, 25, limit)?;\n\nassert_eq!(cursor.next_page()?, first);\nlet metadata = PageMetadata::new(\n    first,\n    25,\n    None,\n    Some(second),\n    Some(second),\n    Some(30),\n)?;\nlet boundary = cursor.observe(metadata, 25, None)?;\n\nassert!(!boundary.is_terminal());\nassert_eq!(cursor.next_page()?, second);\n# Ok(())\n# }\n```\n\nThe caller fetches and decodes each requested page, then passes only validated\nmetadata and the decoded entry count to the cursor. Empty non-terminal pages,\nrepeated pages, contradictory navigation, entries above `per_page`, mismatch\nwith a supplied total, page-size or traversal-total changes, and the caller's\nhard page limit fail closed. Restart the traversal when provider metadata\nchanges. Each accepted boundary preserves transport rate-limit metadata.\n\n## Action Polling Example\n\n```rust\nuse core::time::Duration;\nuse cloud_sdk::action_polling::{\n    ActionPollStep, ActionPoller, ActionUpdate, PollContext, PollDecision,\n    PollPolicy,\n};\n\nstruct FixedDelay;\n\nimpl PollPolicy for FixedDelay {\n    type Error = ();\n\n    fn decide(\u0026mut self, _context: PollContext) -\u003e Result\u003cPollDecision, Self::Error\u003e {\n        Ok(PollDecision::Delay(Duration::from_secs(2)))\n    }\n}\n\nlet mut poller = ActionPoller::new();\nlet mut policy = FixedDelay;\nlet running = poller.observe(\n    ActionUpdate::\u003c()\u003e::Running,\n    25,\n    None,\n    \u0026mut policy,\n);\nassert_eq!(running, Ok(ActionPollStep::Delay(Duration::from_secs(2))));\n\nlet complete = poller.observe(\n    ActionUpdate::\u003c()\u003e::Success,\n    100,\n    None,\n    \u0026mut policy,\n);\nassert_eq!(complete, Ok(ActionPollStep::Complete));\n```\n\nProvider failures are returned as `ActionPollStep::Failed(E)` without being\ndiscarded. Running observations invoke caller policy, which must explicitly\nchoose a nonzero delay, cancellation, or timeout; the SDK owns no clock,\nexecutor, sleep, retry count, or deadline.\n\n## Fixed Buffer Example\n\n```rust\nuse cloud_sdk::buffer::write_query_u64;\n\n# fn main() -\u003e Result\u003c(), ()\u003e {\nlet mut output = [0u8; 8];\nlet mut len = 0;\nlet mut first = true;\nwrite_query_u64(\u0026mut output, \u0026mut len, \u0026mut first, \"page\", 0, ())?;\n\nlet query = output\n    .get(..len)\n    .and_then(|bytes| core::str::from_utf8(bytes).ok());\nassert_eq!(query, Some(\"page=0\"));\n# Ok(())\n# }\n```\n\n## JSON String Example\n\n```rust\nuse cloud_sdk::buffer::write_json_string;\n\n# fn main() -\u003e Result\u003c(), ()\u003e {\nlet mut output = [0u8; 48];\nlet mut len = 0;\nwrite_json_string(\u0026mut output, \u0026mut len, \"line\\n\\\"quoted\\\"\", ())?;\n\nlet value = output\n    .get(..len)\n    .and_then(|bytes| core::str::from_utf8(bytes).ok());\nassert_eq!(value, Some(\"\\\"line\\\\n\\\\\\\"quoted\\\\\\\"\\\"\"));\n# Ok(())\n# }\n```\n\n## Workspace Crates\n\n| Crate | Default `std`? | Purpose |\n| --- | --- | --- |\n| [`cloud-sdk`](https://crates.io/crates/cloud-sdk) | no | Provider-neutral domains, prepared operations, and checked response policy. |\n| [`cloud-sdk-hetzner`](https://crates.io/crates/cloud-sdk-hetzner) | no | Hetzner provider APIs and provider-specific documentation. |\n| [`cloud-sdk-reqwest`](https://crates.io/crates/cloud-sdk-reqwest) | no | Provider-neutral optional blocking and async reqwest/rustls transports; transport-free by default. |\n| [`cloud-sdk-testkit`](https://crates.io/crates/cloud-sdk-testkit) | no | Provider-neutral blocking/async mock transport, prepared-request records, response fixtures, and adversarial corpus. |\n| [`cloud-sdk-sanitization`](https://crates.io/crates/cloud-sdk-sanitization) | no | Provider-neutral volatile caller-buffer cleanup plus optional owned UTF-8 secret storage. |\n\nEach provider has one primary crate for its APIs and documentation. Reusable\ntransport, testing, and secret-handling capabilities remain provider-neutral.\n\n## Provider Documentation\n\nProvider-specific API coverage and maintenance procedures live outside this\nprovider-neutral README. For Hetzner, see the\n[`cloud-sdk-hetzner` crate](https://crates.io/crates/cloud-sdk-hetzner), the\n[API matrix](https://github.com/valkyoth/cloud-sdk/blob/main/docs/API_MATRIX.md),\nand the\n[source-lock policy](https://github.com/valkyoth/cloud-sdk/blob/main/docs/SPEC_LOCK.md),\nand the\n[API drift maintenance runbook](https://github.com/valkyoth/cloud-sdk/blob/main/docs/API_DRIFT_MAINTENANCE.md).\n\n## Development Checks\n\nRun `scripts/checks.sh` for the maintained local check suite. The complete\npentest, CI, release-gate, tagging, and publication process is documented in\nthe [release runbook](https://github.com/valkyoth/cloud-sdk/blob/main/docs/RELEASE_RUNBOOK.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalkyoth%2Fcloud-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalkyoth%2Fcloud-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalkyoth%2Fcloud-sdk/lists"}