<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevCloud</title><link>https://skyoo2003.github.io/devcloud/</link><description>Recent content on DevCloud</description><generator>Hugo</generator><language>en</language><atom:link href="https://skyoo2003.github.io/devcloud/index.xml" rel="self" type="application/rss+xml"/><item><title/><link>https://skyoo2003.github.io/devcloud/architecture/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/architecture/</guid><description>&lt;h1 id="architecture"&gt;Architecture&lt;a class="anchor" href="#architecture"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;DevCloud is a single Go binary that serves cloud provider APIs locally. It targets&#10;&lt;strong&gt;AWS today&lt;/strong&gt;; the seams that let a second CSP join are described at the bottom.&lt;/p&gt;&#10;&lt;h2 id="request-flow"&gt;Request Flow&lt;a class="anchor" href="#request-flow"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;Client (boto3 / AWS CLI / Terraform / CDK)&#10; │&#10; ▼&#10;API Gateway (port 4747)&#10; │&#10; ├─ Middleware Chain&#10; │ ├─ ErrorRecovery (panic recovery)&#10; │ ├─ BodyLimit (request size limiting)&#10; │ ├─ CORS (cross-origin handling)&#10; │ ├─ RequestID (X-Amz-Request-Id)&#10; │ ├─ RequestLogger (structured logging)&#10; │ ├─ Identity (auth.Adapter → claimed identity on the request context)&#10; │ └─ LogCollector (admin API live logs)&#10; │&#10; ├─ Route: /devcloud/api/* → Admin API&#10; │&#10; ▼&#10;Protocol Detector&#10; │&#10; ├─ X-Amz-Target header present → JSON protocol&#10; ├─ x-www-form-urlencoded + Action= → Query protocol&#10; ├─ SigV4 credential scope → REST-JSON (signing name picks the service)&#10; └─ Default → REST-XML (S3)&#10; │&#10; ▼&#10;Service Router → Plugin Registry → ServicePlugin.HandleRequest()&#10; │&#10; ├─ returns plugin.ErrUnhandledOp → generic CRUD engine (docs/crud-engine.md)&#10; │&#10; ▼&#10;Storage Backend → Response Serializer → HTTP Response&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="plugin-system"&gt;Plugin System&lt;a class="anchor" href="#plugin-system"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Every service implements &lt;code&gt;ServicePlugin&lt;/code&gt;:&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/compatibility-policy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/compatibility-policy/</guid><description>&lt;h1 id="compatibility-policy"&gt;Compatibility Policy&lt;a class="anchor" href="#compatibility-policy"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;What DevCloud &lt;strong&gt;v1.0&lt;/strong&gt; promises, and what it deliberately does not.&lt;/p&gt;&#10;&lt;p&gt;This covers the surfaces you touch as a &lt;em&gt;user&lt;/em&gt;: the config file, the environment, the CLI, the&#10;admin API, and the AWS wire protocol. For the in-tree Go contract that service implementations&#10;are written against, see &lt;a href="https://skyoo2003.github.io/devcloud/plugin-api/#api-stability"&gt;plugin-api.md&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Versions follow &lt;a href="https://semver.org"&gt;Semantic Versioning&lt;/a&gt;. &amp;ldquo;Across 1.x&amp;rdquo; means every release&#10;from v1.0.0 up to but not including v2.0.0.&lt;/p&gt;&#10;&lt;h2 id="guaranteed-across-1x"&gt;Guaranteed across 1.x&lt;a class="anchor" href="#guaranteed-across-1x"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h3 id="configuration-file"&gt;Configuration file&lt;a class="anchor" href="#configuration-file"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;These keys keep their name, type and meaning. New keys may be added; existing ones are not&#10;removed or repurposed. Defined in &lt;a href="https://github.com/skyoo2003/devcloud/blob/main/internal/config/config.go"&gt;&lt;code&gt;internal/config/config.go&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/configuration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/configuration/</guid><description>&lt;h1 id="configuration"&gt;Configuration&lt;a class="anchor" href="#configuration"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;Configuration is optional.&lt;/strong&gt; With no flags, &lt;code&gt;devcloud&lt;/code&gt; enables every registered&#10;service on port 4747 and stores data under &lt;code&gt;./data/&amp;lt;service&amp;gt;/&lt;/code&gt;. The defaults are&#10;compiled into the binary from&#10;&lt;a href="https://github.com/skyoo2003/devcloud/blob/main/internal/config/default.yaml"&gt;&lt;code&gt;internal/config/default.yaml&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Config is resolved in this order, and &lt;strong&gt;environment beats YAML beats embedded&#10;default&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;--config &amp;lt;path&amp;gt;&lt;/code&gt; — explicit; the file must exist&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;./devcloud.yaml&lt;/code&gt; in the working directory — auto-detected&lt;/li&gt;&#10;&lt;li&gt;Embedded defaults&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="environment-variables"&gt;Environment variables&lt;a class="anchor" href="#environment-variables"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Variable&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Overrides&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;DEVCLOUD_PORT&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;server.port&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HTTP server port&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;DEVCLOUD_SERVICES&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;services.*.enabled&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Comma-separated service list, or a tier shortcut&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;DEVCLOUD_DATA_DIR&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;services.*.data_dir&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Base data directory for all services&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3 id="devcloud_services"&gt;&lt;code&gt;DEVCLOUD_SERVICES&lt;/code&gt;&lt;a class="anchor" href="#devcloud_services"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;When set, it names the running set outright: &lt;strong&gt;only&lt;/strong&gt; the listed services start,&#10;regardless of their &lt;code&gt;enabled&lt;/code&gt; setting, and a service the &lt;code&gt;services&lt;/code&gt; block omits&#10;entirely still starts if you name it here (the block still supplies its&#10;&lt;code&gt;data_dir&lt;/code&gt;). When unset, each service uses its YAML &lt;code&gt;enabled&lt;/code&gt; value. An unknown&#10;&lt;code&gt;tierN&lt;/code&gt; token is treated as a literal service name and logged as a warning.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/contributing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/contributing/</guid><description>&lt;h1 id="contributing"&gt;Contributing&lt;a class="anchor" href="#contributing"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="prerequisites"&gt;Prerequisites&lt;a class="anchor" href="#prerequisites"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Go 1.26+&lt;/li&gt;&#10;&lt;li&gt;Python 3.10+ with pip (compatibility tests)&lt;/li&gt;&#10;&lt;li&gt;Docker (optional — Lambda runtime and integration tests)&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;pre-commit&lt;/code&gt; (optional but recommended)&lt;/li&gt;&#10;&lt;li&gt;Hugo extended 0.165+ (optional — only to preview this documentation as a site)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;No C toolchain and no SQLite headers: the SQLite driver is pure Go, which is why&#10;everything here builds with &lt;code&gt;CGO_ENABLED=0&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2 id="setup"&gt;Setup&lt;a class="anchor" href="#setup"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone https://github.com/skyoo2003/devcloud.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd devcloud&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make build &lt;span style="color:#75715e"&gt;# builds dist/devcloud and dist/codegen&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make run &lt;span style="color:#75715e"&gt;# starts the server on port 4747&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="make-targets"&gt;Make Targets&lt;a class="anchor" href="#make-targets"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;!-- AUTO-GENERATED: from Makefile. Do not edit by hand. --&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Command&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make build&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Build both binaries into &lt;code&gt;dist/&lt;/code&gt; — &lt;code&gt;devcloud&lt;/code&gt; and &lt;code&gt;codegen&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make run&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Run the server from source (&lt;code&gt;go run ./cmd/devcloud&lt;/code&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make test&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Run all Go tests with &lt;code&gt;CGO_ENABLED=0&lt;/code&gt; and &lt;code&gt;-v&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make test-compat&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Install &lt;code&gt;tests/compatibility/requirements.txt&lt;/code&gt; and run the boto3 suite&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make codegen&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Regenerate &lt;code&gt;internal/generated/&lt;/code&gt; from every model in &lt;code&gt;smithy-models/&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make codegen-s3&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Same, restricted to S3 — fast loop while editing templates&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make docker-build&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Build the image from &lt;code&gt;docker/Dockerfile&lt;/code&gt; as &lt;code&gt;devcloud/devcloud&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make docker-run&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Run that image on port 4747 with &lt;code&gt;./data&lt;/code&gt; mounted&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make docs-serve&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Preview this documentation locally with Hugo&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make docs-build&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Build the documentation site and check every internal link&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make clean&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Delete &lt;code&gt;dist/&lt;/code&gt;, &lt;code&gt;data/&lt;/code&gt;, and the Hugo output in &lt;code&gt;public/&lt;/code&gt; and &lt;code&gt;resources/&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make changelog VERSION=vX.Y.Z&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Batch and merge Changie fragments; &lt;code&gt;VERSION&lt;/code&gt; is required&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;make stats&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Print registered service and operation counts&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;!-- END AUTO-GENERATED --&gt;&#10;&lt;h2 id="testing"&gt;Testing&lt;a class="anchor" href="#testing"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make test &lt;span style="color:#75715e"&gt;# Go tests, CGO_ENABLED=0 — the same mode releases ship&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make test-compat &lt;span style="color:#75715e"&gt;# Python/boto3 suite in tests/compatibility/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You do &lt;strong&gt;not&lt;/strong&gt; need a server running first. The &lt;code&gt;devcloud_server&lt;/code&gt; session fixture&#10;in &lt;a href="https://github.com/skyoo2003/devcloud/blob/main/tests/compatibility/conftest.py"&gt;&lt;code&gt;conftest.py&lt;/code&gt;&lt;/a&gt; starts one via &lt;code&gt;go run&lt;/code&gt;, on&#10;a free port, against a temporary data directory it removes afterwards. Three&#10;environment variables change that:&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/coverage/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/coverage/</guid><description>&lt;h1 id="coverage"&gt;Coverage&lt;a class="anchor" href="#coverage"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Three numbers describe DevCloud&amp;rsquo;s AWS surface, and they mean different things.&#10;The service count alone is not a capability claim, so this page never states it&#10;alone.&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Number&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;What it means&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Today&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Registered&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The gateway routes the service, so the call reaches DevCloud instead of real AWS.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;205&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Serving ≥1 operation&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;At least one operation returns a real, store-backed answer.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;201&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Registered-only&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Routed, but every operation declines with a clean AWS error.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Compatibility-tested&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;A boto3 test exercises the service in CI and passes.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;203&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Per operation, from the &lt;a href="https://skyoo2003.github.io/devcloud/fidelity-manifest/"&gt;fidelity manifest&lt;/a&gt;:&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/crud-engine/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/crud-engine/</guid><description>&lt;h1 id="generic-crud-fallback-engine"&gt;Generic CRUD Fallback Engine&lt;a class="anchor" href="#generic-crud-fallback-engine"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;DevCloud auto-serves standard CRUD-shaped operations that a service&amp;rsquo;s hand-written&#10;provider has not implemented, using a generic engine driven by the Smithy models.&#10;This is what lets the long tail respond to SDK calls without hand-coding each one.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Fidelity is deliberately &amp;ldquo;plausible, not faithful.&amp;rdquo;&lt;/strong&gt; Responses are store-backed&#10;and echo the caller&amp;rsquo;s input plus synthesized ids and ARNs, so SDKs round-trip&#10;create → get → list → delete. There is &lt;strong&gt;no&lt;/strong&gt; validation, cross-resource&#10;integrity, pagination correctness, or business logic. Treat engine-served&#10;operations as scaffolding for local wiring, not as behavioural parity.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/demand/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/demand/</guid><description>&lt;h1 id="demand-for-unregistered-services"&gt;Demand for unregistered services&lt;a class="anchor" href="#demand-for-unregistered-services"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;The evidence behind DevCloud&amp;rsquo;s &lt;a href="https://skyoo2003.github.io/devcloud/coverage/#the-target"&gt;coverage target&lt;/a&gt;.&#10;Sampled 2026-09-05; re-derive with &lt;code&gt;python3 scripts/demand_rank.py&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2 id="what-this-measures"&gt;What this measures&lt;a class="anchor" href="#what-this-measures"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;DevCloud has no usage telemetry, so this page does &lt;strong&gt;not&lt;/strong&gt; measure what its users&#10;ask for. It measures &lt;em&gt;revealed&lt;/em&gt; demand: how many of three independent projects&#10;have already built each AWS service DevCloud does not register. Each serves a&#10;population DevCloud names as its own, and each only adds a service when somebody&#10;asks.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/faq/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/faq/</guid><description>&lt;h1 id="faq"&gt;FAQ&lt;a class="anchor" href="#faq"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="general"&gt;General&lt;a class="anchor" href="#general"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;What is DevCloud?&lt;/strong&gt;&#10;A local, API-compatible cloud environment for inner-loop development. Run it on your laptop or in CI and point your AWS SDKs, CLI or Terraform at it instead of real AWS.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Is it a production service?&lt;/strong&gt;&#10;No. It is a local development tool, not designed or tested for production, and should not be exposed to untrusted networks. See &lt;a href="https://github.com/skyoo2003/devcloud/blob/main/SECURITY.md"&gt;SECURITY.md&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;How is it different from other local cloud emulators?&lt;/strong&gt;&#10;DevCloud positions itself as an &lt;em&gt;on-ramp&lt;/em&gt; rather than a replacement:&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/fidelity-manifest/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/fidelity-manifest/</guid><description>&lt;h1 id="fidelity-manifest"&gt;Fidelity Manifest&lt;a class="anchor" href="#fidelity-manifest"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Not every operation is served the same way. The &lt;strong&gt;fidelity manifest&lt;/strong&gt; answers, per&#10;operation, &lt;em&gt;how much you can trust this call&lt;/em&gt; — so a green response never leaves&#10;you guessing whether DevCloud implemented the operation or made something&#10;plausible up.&lt;/p&gt;&#10;&lt;p&gt;It is generated, never hand-written: &lt;code&gt;make codegen&lt;/code&gt; derives it from the in-tree&#10;Smithy models, the CRUD registry, and each provider&amp;rsquo;s dispatch code. Current&#10;totals are published in &lt;a href="https://skyoo2003.github.io/devcloud/coverage/"&gt;coverage.md&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="tiers"&gt;Tiers&lt;a class="anchor" href="#tiers"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Tier&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Meaning&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Trust it for&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;hand-verified&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The service&amp;rsquo;s provider implements the operation explicitly.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Behaviour, not just shape. Covered by the boto3 suite where tests exist.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;auto-crud&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Served by the &lt;a href="https://skyoo2003.github.io/devcloud/crud-engine/"&gt;generic CRUD engine&lt;/a&gt;: store-backed, plausible responses with no validation, business logic, or cross-resource integrity.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Wiring your SDK up and round-tripping create → get → list → delete. Nothing else.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;unimplemented&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Not served — the call fails instead of inventing a success.&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Knowing early that DevCloud will not serve this call.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;code&gt;hand-verified&lt;/code&gt; always wins: the CRUD engine is reached only when a provider&amp;rsquo;s&#10;dispatch falls through, so a hand-written implementation is never shadowed.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/getting-started/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/getting-started/</guid><description>&lt;h1 id="getting-started"&gt;Getting Started&lt;a class="anchor" href="#getting-started"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="run-with-docker-recommended"&gt;Run with Docker (recommended)&lt;a class="anchor" href="#run-with-docker-recommended"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -p 4747:4747 ghcr.io/skyoo2003/devcloud:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To persist data across restarts, mount a volume:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -p 4747:4747 -v &lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;pwd&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;/data:/app/data ghcr.io/skyoo2003/devcloud:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-compose-development"&gt;Docker Compose (development)&lt;a class="anchor" href="#docker-compose-development"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker compose -f docker/docker-compose.yml up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Builds the image from source and starts the Go server on port 4747 with &lt;code&gt;./data&lt;/code&gt;&#10;mounted. It runs a subset, not everything —&#10;&lt;a href="https://github.com/skyoo2003/devcloud/blob/main/docker/docker-compose.yml"&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/a&gt; sets&#10;&lt;code&gt;DEVCLOUD_SERVICES=s3,sqs,dynamodb,iam,sts,lambda&lt;/code&gt;. Edit that line, or see&#10;&lt;a href="https://skyoo2003.github.io/devcloud/configuration/#devcloud_services"&gt;Configuration&lt;/a&gt;, to run more.&lt;/p&gt;&#10;&lt;h2 id="build-from-source"&gt;Build from source&lt;a class="anchor" href="#build-from-source"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Recommended only for contributors — see &lt;a href="https://skyoo2003.github.io/devcloud/contributing/"&gt;contributing.md&lt;/a&gt; for&#10;full prerequisites and workflow.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/plugin-api/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/plugin-api/</guid><description>&lt;h1 id="serviceplugin-api"&gt;ServicePlugin API&lt;a class="anchor" href="#serviceplugin-api"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;The stable contract every DevCloud service implements. As of &lt;strong&gt;v1.0&lt;/strong&gt; this is a&#10;public API — see &lt;a href="#api-stability"&gt;API stability&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;The interface and registry live in &lt;a href="https://github.com/skyoo2003/devcloud/tree/main/internal/plugin"&gt;&lt;code&gt;internal/plugin/&lt;/code&gt;&lt;/a&gt;.&#10;Plugins are compiled in-tree and register themselves at startup; there is no&#10;dynamic loading. (That is why the package is under &lt;code&gt;internal/&lt;/code&gt; — it is imported&#10;by DevCloud&amp;rsquo;s own binaries, not by third-party modules.)&lt;/p&gt;&#10;&lt;h2 id="the-interface"&gt;The interface&lt;a class="anchor" href="#the-interface"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServicePlugin&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ServiceID&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ServiceName&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Protocol&lt;/span&gt;() &lt;span style="color:#a6e22e"&gt;ProtocolType&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Init&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;config&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PluginConfig&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Shutdown&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;HandleRequest&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;op&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;req&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Request&lt;/span&gt;) (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Response&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ListResources&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) ([]&lt;span style="color:#a6e22e"&gt;Resource&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Method&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Contract&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ServiceID()&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Stable lowercase identifier, e.g. &lt;code&gt;&amp;quot;s3&amp;quot;&lt;/code&gt;. &lt;strong&gt;Must equal the key the plugin is registered under&lt;/strong&gt; — the gateway routes by it. Constant; safe before &lt;code&gt;Init&lt;/code&gt;.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ServiceName()&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Human-readable name for logs and the admin API. Non-empty, constant, safe before &lt;code&gt;Init&lt;/code&gt;.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;Protocol()&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;One of the &lt;a href="#protocols"&gt;&lt;code&gt;ProtocolType&lt;/code&gt;&lt;/a&gt; constants. Constant; safe before &lt;code&gt;Init&lt;/code&gt;.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;Init(config)&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Called once at startup before any request. Open stores, read &lt;code&gt;config.Options&lt;/code&gt;. A non-nil error aborts startup (services in the fixed init order) or skips the service (others).&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;Shutdown(ctx)&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Called once at graceful shutdown, 15s budget. Flush and close. Idempotent-friendly.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;HandleRequest(ctx, op, req)&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Handle one API call. See &lt;a href="#operation-names"&gt;operation names&lt;/a&gt; — &lt;code&gt;op&lt;/code&gt; may be &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt; for REST protocols, in which case derive it yourself. Return a &lt;code&gt;*Response&lt;/code&gt;; return a Go &lt;code&gt;error&lt;/code&gt; only for unexpected internal failures (the gateway wraps those as &lt;code&gt;500 InternalError&lt;/code&gt;). &lt;strong&gt;Model AWS errors as a normal &lt;code&gt;*Response&lt;/code&gt;.&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;ListResources(ctx)&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The resources this service currently holds, for the admin API. May be empty.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;These invariants are enforced for every registered service by&#10;&lt;a href="https://github.com/skyoo2003/devcloud/blob/main/cmd/devcloud/conformance_test.go"&gt;&lt;code&gt;TestServicePluginConformance&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/roadmap/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/roadmap/</guid><description>&lt;h1 id="roadmap"&gt;Roadmap&lt;a class="anchor" href="#roadmap"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;DevCloud aims to be a &lt;strong&gt;local development companion for cloud-native apps across&#10;every major CSP&lt;/strong&gt; — not a production replacement, but an on-ramp that lets you&#10;iterate without cloud bills and deploy to your target CSP with confidence. It gets&#10;there in phases, to keep scope, architectural complexity and community&#10;expectations manageable.&lt;/p&gt;&#10;&lt;h2 id="guiding-principles"&gt;Guiding principles&lt;a class="anchor" href="#guiding-principles"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;Local-first, cost-free&lt;/strong&gt; — no cloud charges for inner-loop development.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;On-ramp, not replacement&lt;/strong&gt; — DevCloud helps you &lt;em&gt;land on&lt;/em&gt; a CSP, not avoid it.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;API-compatible, not behaviour-perfect&lt;/strong&gt; — SDK compatibility over edge-case parity.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Community-owned&lt;/strong&gt; — the scope is too large for one maintainer, so the plugin architecture and contributor experience are first-class.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Trademark-respectful&lt;/strong&gt; — see &lt;a href="https://github.com/skyoo2003/devcloud/blob/main/TRADEMARKS.md"&gt;TRADEMARKS.md&lt;/a&gt;.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="phase-1--aws-depth-and-stabilization-complete-shipped-as-v10"&gt;Phase 1 — AWS depth and stabilization (complete, shipped as v1.0)&lt;a class="anchor" href="#phase-1--aws-depth-and-stabilization-complete-shipped-as-v10"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Mature the already-broad AWS surface into a stable, well-tested v1.0.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/services-matrix/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/services-matrix/</guid><description>&lt;h1 id="services-matrix"&gt;Services Matrix&lt;a class="anchor" href="#services-matrix"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;Which AWS services DevCloud serves, and how deeply.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Counts live in &lt;a href="https://skyoo2003.github.io/devcloud/coverage/"&gt;coverage.md&lt;/a&gt;&lt;/strong&gt; — it is the only page that publishes&#10;them, and CI fails if its figures and the binary disagree. This page describes the&#10;&lt;em&gt;shape&lt;/em&gt; of the surface instead.&lt;/p&gt;&#10;&lt;h2 id="how-to-look-up-one-service"&gt;How to look up one service&lt;a class="anchor" href="#how-to-look-up-one-service"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Per-operation depth is declared by the generated&#10;&lt;a href="https://skyoo2003.github.io/devcloud/fidelity-manifest/"&gt;fidelity manifest&lt;/a&gt;, not by a hand-maintained table. Ask it&#10;directly (requires &lt;code&gt;admin.enabled: true&lt;/code&gt;):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s &lt;span style="color:#e6db74"&gt;&amp;#39;localhost:4747/devcloud/api/fidelity?service=s3&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Tier&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;What it means&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;hand-verified&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The service&amp;rsquo;s provider implements the operation explicitly.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;auto-crud&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Served by the &lt;a href="https://skyoo2003.github.io/devcloud/crud-engine/"&gt;CRUD engine&lt;/a&gt; — store-backed and plausible, not faithful.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;unimplemented&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Refused with an AWS-shaped error. Never a fabricated success.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="depth-by-group"&gt;Depth by group&lt;a class="anchor" href="#depth-by-group"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Group&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Services&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Depth&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Core&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;S3, SQS, DynamoDB, Lambda, IAM, STS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hand-written throughout; the deepest boto3 coverage&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Integration&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SNS, EventBridge, CloudWatch, CW Logs, KMS, Secrets Manager, SSM, ECR, CloudFormation&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hand-written common operations, plus the cross-service wiring below&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Extended&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;EC2, ECS, EKS, Route53, ACM, RDS, Kinesis, Firehose, SFN, Bedrock, and the rest of the registered set&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Common operations hand-written; the long tail is engine-served or declines cleanly&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;The &lt;code&gt;tier1&lt;/code&gt; / &lt;code&gt;tier2&lt;/code&gt; / &lt;code&gt;tier3&lt;/code&gt; tokens accepted by &lt;code&gt;DEVCLOUD_SERVICES&lt;/code&gt; are a&#10;&lt;em&gt;startup&lt;/em&gt; grouping, not a depth claim — see&#10;&lt;a href="https://skyoo2003.github.io/devcloud/configuration/#devcloud_services"&gt;configuration.md&lt;/a&gt; for their exact contents.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/services/dynamodb/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/services/dynamodb/</guid><description>&lt;h1 id="dynamodb"&gt;DynamoDB&lt;a class="anchor" href="#dynamodb"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="overview"&gt;Overview&lt;a class="anchor" href="#overview"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;DevCloud DynamoDB uses BadgerDB as its embedded key-value storage backend. Table metadata is kept in an in-memory index (protected by RWMutex), while items are persisted in BadgerDB with composite keys (&lt;code&gt;_item/{table}#{partitionKey}#{sortKey}&lt;/code&gt;).&lt;/p&gt;&#10;&lt;p&gt;Supported attribute types: S (String), N (Number), B (Binary), BOOL, NULL, L (List), M (Map).&lt;/p&gt;&#10;&lt;h2 id="supported-apis"&gt;Supported APIs&lt;a class="anchor" href="#supported-apis"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Operation&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CreateTable&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Create table with partition key (HASH) and optional sort key (RANGE)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DeleteTable&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Delete table and all its items&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ListTables&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;List all table names&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PutItem&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Insert or overwrite an item&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GetItem&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Retrieve an item by primary key&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DeleteItem&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Delete an item by primary key&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Query&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Query items by partition key&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Scan&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Full table scan&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="boto3-examples"&gt;boto3 Examples&lt;a class="anchor" href="#boto3-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h3 id="create-a-table-and-write-items"&gt;Create a table and write items&lt;a class="anchor" href="#create-a-table-and-write-items"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; boto3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dynamodb &lt;span style="color:#f92672"&gt;=&lt;/span&gt; boto3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;client(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;dynamodb&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint_url&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:4747&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_access_key_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_secret_access_key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; region_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create table&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dynamodb&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_table(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TableName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;users&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KeySchema&lt;span style="color:#f92672"&gt;=&lt;/span&gt;[&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;AttributeName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;pk&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;KeyType&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;HASH&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;AttributeName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;sk&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;KeyType&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;RANGE&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AttributeDefinitions&lt;span style="color:#f92672"&gt;=&lt;/span&gt;[&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;AttributeName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;pk&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;AttributeType&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;AttributeName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;sk&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;AttributeType&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BillingMode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;PAY_PER_REQUEST&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Put item&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dynamodb&lt;span style="color:#f92672"&gt;.&lt;/span&gt;put_item(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TableName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;users&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Item&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;pk&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;user#123&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;sk&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;profile&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;age&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;N&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;30&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get item&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; dynamodb&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get_item(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TableName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;users&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;pk&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;user#123&amp;#34;&lt;/span&gt;}, &lt;span style="color:#e6db74"&gt;&amp;#34;sk&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;profile&amp;#34;&lt;/span&gt;}},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(response[&lt;span style="color:#e6db74"&gt;&amp;#34;Item&amp;#34;&lt;/span&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="query-and-scan"&gt;Query and scan&lt;a class="anchor" href="#query-and-scan"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Query by partition key&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; dynamodb&lt;span style="color:#f92672"&gt;.&lt;/span&gt;query(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TableName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;users&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KeyConditionExpression&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;pk = :pk&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ExpressionAttributeValues&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;:pk&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;S&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;user#123&amp;#34;&lt;/span&gt;}},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; item &lt;span style="color:#f92672"&gt;in&lt;/span&gt; response[&lt;span style="color:#e6db74"&gt;&amp;#34;Items&amp;#34;&lt;/span&gt;]:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(item)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Full table scan&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; dynamodb&lt;span style="color:#f92672"&gt;.&lt;/span&gt;scan(TableName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;users&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; item &lt;span style="color:#f92672"&gt;in&lt;/span&gt; response[&lt;span style="color:#e6db74"&gt;&amp;#34;Items&amp;#34;&lt;/span&gt;]:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(item)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="aws-cli-examples"&gt;AWS CLI Examples&lt;a class="anchor" href="#aws-cli-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create table&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 dynamodb create-table &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --table-name my-table &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --key-schema AttributeName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;pk,KeyType&lt;span style="color:#f92672"&gt;=&lt;/span&gt;HASH &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --attribute-definitions AttributeName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;pk,AttributeType&lt;span style="color:#f92672"&gt;=&lt;/span&gt;S &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --billing-mode PAY_PER_REQUEST&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Put item&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 dynamodb put-item &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --table-name my-table &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --item &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;pk&amp;#34;: {&amp;#34;S&amp;#34;: &amp;#34;key1&amp;#34;}, &amp;#34;data&amp;#34;: {&amp;#34;S&amp;#34;: &amp;#34;value1&amp;#34;}}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get item&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 dynamodb get-item &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --table-name my-table &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --key &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;pk&amp;#34;: {&amp;#34;S&amp;#34;: &amp;#34;key1&amp;#34;}}&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="known-limitations"&gt;Known Limitations&lt;a class="anchor" href="#known-limitations"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;No UpdateItem (use PutItem to overwrite entire item)&lt;/li&gt;&#10;&lt;li&gt;No batch operations (BatchGetItem, BatchWriteItem)&lt;/li&gt;&#10;&lt;li&gt;No transactions (TransactGetItems, TransactWriteItems)&lt;/li&gt;&#10;&lt;li&gt;No secondary indexes (GSI/LSI)&lt;/li&gt;&#10;&lt;li&gt;No DynamoDB Streams&lt;/li&gt;&#10;&lt;li&gt;No advanced filter expressions on Query/Scan&lt;/li&gt;&#10;&lt;li&gt;No projection expressions&lt;/li&gt;&#10;&lt;li&gt;No conditional writes (ConditionExpression)&lt;/li&gt;&#10;&lt;li&gt;No TTL&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/services/iam-sts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/services/iam-sts/</guid><description>&lt;h1 id="iam--sts"&gt;IAM / STS&lt;a class="anchor" href="#iam--sts"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="overview"&gt;Overview&lt;a class="anchor" href="#overview"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;DevCloud IAM and STS share a single SQLite database (WAL mode). IAM manages users, roles, and access keys. STS generates temporary credentials and caller identity information.&lt;/p&gt;&#10;&lt;p&gt;Both services use the Query protocol (form-encoded requests, XML responses).&lt;/p&gt;&#10;&lt;h2 id="supported-iam-apis"&gt;Supported IAM APIs&lt;a class="anchor" href="#supported-iam-apis"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Operation&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CreateUser&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Create an IAM user&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ListUsers&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;List all IAM users&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CreateRole&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Create an IAM role with assume role policy document&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ListRoles&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;List all IAM roles&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AttachRolePolicy&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Attach a managed policy ARN to a role&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CreateAccessKey&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Generate an access key pair for a user&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="supported-sts-apis"&gt;Supported STS APIs&lt;a class="anchor" href="#supported-sts-apis"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Operation&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GetCallerIdentity&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Return account ID, ARN, and user ID&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AssumeRole&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Generate temporary credentials (ASIA-prefixed keys, 1-hour expiry)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GetSessionToken&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Generate MFA-backed session credentials&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="boto3-examples"&gt;boto3 Examples&lt;a class="anchor" href="#boto3-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h3 id="iam-create-users-and-roles"&gt;IAM: Create users and roles&lt;a class="anchor" href="#iam-create-users-and-roles"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; boto3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;iam &lt;span style="color:#f92672"&gt;=&lt;/span&gt; boto3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;client(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;iam&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint_url&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:4747&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_access_key_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_secret_access_key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; region_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create user&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;iam&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_user(UserName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;testuser&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create access key for user&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;keys &lt;span style="color:#f92672"&gt;=&lt;/span&gt; iam&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_access_key(UserName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;testuser&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(keys[&lt;span style="color:#e6db74"&gt;&amp;#34;AccessKey&amp;#34;&lt;/span&gt;][&lt;span style="color:#e6db74"&gt;&amp;#34;AccessKeyId&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(keys[&lt;span style="color:#e6db74"&gt;&amp;#34;AccessKey&amp;#34;&lt;/span&gt;][&lt;span style="color:#e6db74"&gt;&amp;#34;SecretAccessKey&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create role&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;iam&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_role(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RoleName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;lambda-role&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; AssumeRolePolicyDocument&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;Version&amp;#34;:&amp;#34;2012-10-17&amp;#34;,&amp;#34;Statement&amp;#34;:[]}&amp;#39;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# List users and roles&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; user &lt;span style="color:#f92672"&gt;in&lt;/span&gt; iam&lt;span style="color:#f92672"&gt;.&lt;/span&gt;list_users()[&lt;span style="color:#e6db74"&gt;&amp;#34;Users&amp;#34;&lt;/span&gt;]:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(user[&lt;span style="color:#e6db74"&gt;&amp;#34;UserName&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; role &lt;span style="color:#f92672"&gt;in&lt;/span&gt; iam&lt;span style="color:#f92672"&gt;.&lt;/span&gt;list_roles()[&lt;span style="color:#e6db74"&gt;&amp;#34;Roles&amp;#34;&lt;/span&gt;]:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(role[&lt;span style="color:#e6db74"&gt;&amp;#34;RoleName&amp;#34;&lt;/span&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="sts-get-caller-identity-and-assume-role"&gt;STS: Get caller identity and assume role&lt;a class="anchor" href="#sts-get-caller-identity-and-assume-role"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sts &lt;span style="color:#f92672"&gt;=&lt;/span&gt; boto3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;client(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;sts&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint_url&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:4747&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_access_key_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_secret_access_key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; region_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get caller identity&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;identity &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sts&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get_caller_identity()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(identity[&lt;span style="color:#e6db74"&gt;&amp;#34;Account&amp;#34;&lt;/span&gt;]) &lt;span style="color:#75715e"&gt;# 000000000000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(identity[&lt;span style="color:#e6db74"&gt;&amp;#34;Arn&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Assume role&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sts&lt;span style="color:#f92672"&gt;.&lt;/span&gt;assume_role(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RoleArn&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;arn:aws:iam::000000000000:role/lambda-role&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RoleSessionName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-session&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;creds &lt;span style="color:#f92672"&gt;=&lt;/span&gt; response[&lt;span style="color:#e6db74"&gt;&amp;#34;Credentials&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(creds[&lt;span style="color:#e6db74"&gt;&amp;#34;AccessKeyId&amp;#34;&lt;/span&gt;]) &lt;span style="color:#75715e"&gt;# ASIA-prefixed&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(creds[&lt;span style="color:#e6db74"&gt;&amp;#34;SecretAccessKey&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(creds[&lt;span style="color:#e6db74"&gt;&amp;#34;SessionToken&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(creds[&lt;span style="color:#e6db74"&gt;&amp;#34;Expiration&amp;#34;&lt;/span&gt;]) &lt;span style="color:#75715e"&gt;# 1 hour from now&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="aws-cli-examples"&gt;AWS CLI Examples&lt;a class="anchor" href="#aws-cli-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create user&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 iam create-user --user-name testuser&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create access key&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 iam create-access-key --user-name testuser&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get caller identity&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 sts get-caller-identity&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Assume role&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 sts assume-role &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --role-arn arn:aws:iam::000000000000:role/my-role &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --role-session-name my-session&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="known-limitations"&gt;Known Limitations&lt;a class="anchor" href="#known-limitations"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;IAM:&lt;/strong&gt;&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/services/lambda/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/services/lambda/</guid><description>&lt;h1 id="lambda"&gt;Lambda&lt;a class="anchor" href="#lambda"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="overview"&gt;Overview&lt;a class="anchor" href="#overview"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;DevCloud Lambda stores function metadata in SQLite and function code (ZIP files) on the filesystem. Function registration and management are fully supported, but &lt;strong&gt;code execution is currently a stub&lt;/strong&gt; — invoking a function returns a placeholder response instead of running the actual code.&lt;/p&gt;&#10;&lt;h2 id="supported-apis"&gt;Supported APIs&lt;a class="anchor" href="#supported-apis"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Operation&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CreateFunction&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Create function with base64-encoded ZIP code&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ListFunctions&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;List all functions in the account&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GetFunction&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Get function metadata and code location&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DeleteFunction&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Delete a function&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;UpdateFunctionCode&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Update function code ZIP&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Invoke&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Invoke function (stub — returns placeholder response)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="boto3-examples"&gt;boto3 Examples&lt;a class="anchor" href="#boto3-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h3 id="create-and-manage-functions"&gt;Create and manage functions&lt;a class="anchor" href="#create-and-manage-functions"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; boto3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; zipfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; io&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; base64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lambda_client &lt;span style="color:#f92672"&gt;=&lt;/span&gt; boto3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;client(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lambda&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint_url&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:4747&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_access_key_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_secret_access_key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; region_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create a ZIP file with handler code&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;zip_buffer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; io&lt;span style="color:#f92672"&gt;.&lt;/span&gt;BytesIO()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; zipfile&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ZipFile(zip_buffer, &lt;span style="color:#e6db74"&gt;&amp;#34;w&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; zf:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; zf&lt;span style="color:#f92672"&gt;.&lt;/span&gt;writestr(&lt;span style="color:#e6db74"&gt;&amp;#34;index.py&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;def handler(event, context): return {&amp;#34;statusCode&amp;#34;: 200}&amp;#39;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;zip_buffer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;seek(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create function&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lambda_client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_function(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FunctionName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-func&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Runtime&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;python3.12&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Handler&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;index.handler&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Role&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;arn:aws:iam::000000000000:role/lambda-role&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Code&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;ZipFile&amp;#34;&lt;/span&gt;: zip_buffer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read()},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# List functions&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; lambda_client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;list_functions()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; fn &lt;span style="color:#f92672"&gt;in&lt;/span&gt; response[&lt;span style="color:#e6db74"&gt;&amp;#34;Functions&amp;#34;&lt;/span&gt;]:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(fn[&lt;span style="color:#e6db74"&gt;&amp;#34;FunctionName&amp;#34;&lt;/span&gt;], fn[&lt;span style="color:#e6db74"&gt;&amp;#34;Runtime&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get function details&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; lambda_client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get_function(FunctionName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-func&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(response[&lt;span style="color:#e6db74"&gt;&amp;#34;Configuration&amp;#34;&lt;/span&gt;][&lt;span style="color:#e6db74"&gt;&amp;#34;FunctionArn&amp;#34;&lt;/span&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="invoke-function-stub"&gt;Invoke function (stub)&lt;a class="anchor" href="#invoke-function-stub"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; json&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; lambda_client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;invoke(FunctionName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-func&amp;#34;&lt;/span&gt;, Payload&lt;span style="color:#f92672"&gt;=&lt;/span&gt;json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;dumps({&lt;span style="color:#e6db74"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;}))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;loads(response[&lt;span style="color:#e6db74"&gt;&amp;#34;Payload&amp;#34;&lt;/span&gt;]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read()))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# {&amp;#34;statusCode&amp;#34;: 200, &amp;#34;body&amp;#34;: &amp;#34;Lambda invoke requires Docker runtime&amp;#34;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="aws-cli-examples"&gt;AWS CLI Examples&lt;a class="anchor" href="#aws-cli-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create function&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 lambda create-function &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --function-name my-func &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --runtime python3.12 &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --handler index.handler &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --role arn:aws:iam::000000000000:role/role &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --zip-file fileb://code.zip&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# List functions&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 lambda list-functions&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Invoke (returns stub response)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 lambda invoke &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --function-name my-func output.json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="known-limitations"&gt;Known Limitations&lt;a class="anchor" href="#known-limitations"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;No code execution&lt;/strong&gt; — Invoke returns a placeholder response. Docker runtime integration is planned but not yet implemented.&lt;/li&gt;&#10;&lt;li&gt;No layers&lt;/li&gt;&#10;&lt;li&gt;No aliases or versions&lt;/li&gt;&#10;&lt;li&gt;No event source mappings&lt;/li&gt;&#10;&lt;li&gt;No concurrency controls&lt;/li&gt;&#10;&lt;li&gt;No function URLs&lt;/li&gt;&#10;&lt;li&gt;No resource-based policies&lt;/li&gt;&#10;&lt;li&gt;No environment variables support&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/services/s3/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/services/s3/</guid><description>&lt;h1 id="s3-simple-storage-service"&gt;S3 (Simple Storage Service)&lt;a class="anchor" href="#s3-simple-storage-service"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="overview"&gt;Overview&lt;a class="anchor" href="#overview"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;DevCloud S3 provides basic object storage using the filesystem for object data and SQLite for metadata. Objects are stored as files on disk; bucket and object metadata (names, sizes, ETags, content types, timestamps) are tracked in a SQLite database with WAL mode enabled.&lt;/p&gt;&#10;&lt;h2 id="supported-apis"&gt;Supported APIs&lt;a class="anchor" href="#supported-apis"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Operation&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Description&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ListBuckets&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;List all buckets in the account&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CreateBucket&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Create a new bucket&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DeleteBucket&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Delete an empty bucket&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ListObjects&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;List objects in a bucket (supports prefix filtering)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PutObject&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Upload an object (computes MD5 ETag)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GetObject&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Download an object with metadata headers&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HeadObject&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Retrieve object metadata without body&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DeleteObject&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Delete an object from a bucket&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="boto3-examples"&gt;boto3 Examples&lt;a class="anchor" href="#boto3-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h3 id="create-a-bucket-and-upload-an-object"&gt;Create a bucket and upload an object&lt;a class="anchor" href="#create-a-bucket-and-upload-an-object"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; boto3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;s3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; boto3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;client(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;s3&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint_url&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:4747&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_access_key_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; aws_secret_access_key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; region_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create bucket&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;s3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_bucket(Bucket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-bucket&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Upload object&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;s3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;put_object(Bucket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-bucket&amp;#34;&lt;/span&gt;, Key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hello.txt&amp;#34;&lt;/span&gt;, Body&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;b&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Hello, DevCloud!&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Download object&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; s3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get_object(Bucket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-bucket&amp;#34;&lt;/span&gt;, Key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hello.txt&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(response[&lt;span style="color:#e6db74"&gt;&amp;#34;Body&amp;#34;&lt;/span&gt;]&lt;span style="color:#f92672"&gt;.&lt;/span&gt;read()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;decode()) &lt;span style="color:#75715e"&gt;# Hello, DevCloud!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="list-buckets-and-objects"&gt;List buckets and objects&lt;a class="anchor" href="#list-buckets-and-objects"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# List all buckets&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;buckets &lt;span style="color:#f92672"&gt;=&lt;/span&gt; s3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;list_buckets()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; b &lt;span style="color:#f92672"&gt;in&lt;/span&gt; buckets[&lt;span style="color:#e6db74"&gt;&amp;#34;Buckets&amp;#34;&lt;/span&gt;]:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(b[&lt;span style="color:#e6db74"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# List objects in a bucket&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;objects &lt;span style="color:#f92672"&gt;=&lt;/span&gt; s3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;list_objects(Bucket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;my-bucket&amp;#34;&lt;/span&gt;, Prefix&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; obj &lt;span style="color:#f92672"&gt;in&lt;/span&gt; objects&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;Contents&amp;#34;&lt;/span&gt;, []):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(obj[&lt;span style="color:#e6db74"&gt;&amp;#34;Key&amp;#34;&lt;/span&gt;], obj[&lt;span style="color:#e6db74"&gt;&amp;#34;Size&amp;#34;&lt;/span&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="aws-cli-examples"&gt;AWS CLI Examples&lt;a class="anchor" href="#aws-cli-examples"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create bucket&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 s3 mb s3://my-bucket&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Upload file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 s3 cp file.txt s3://my-bucket/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# List objects&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 s3 ls s3://my-bucket/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Download file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws --endpoint-url http://localhost:4747 s3 cp s3://my-bucket/file.txt ./downloaded.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="known-limitations"&gt;Known Limitations&lt;a class="anchor" href="#known-limitations"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;No multipart upload support (CreateMultipartUpload, UploadPart, CompleteMultipartUpload)&lt;/li&gt;&#10;&lt;li&gt;No object versioning or object lock&lt;/li&gt;&#10;&lt;li&gt;No ACL or bucket policy management&lt;/li&gt;&#10;&lt;li&gt;No encryption (SSE-S3, SSE-KMS)&lt;/li&gt;&#10;&lt;li&gt;No CORS configuration&lt;/li&gt;&#10;&lt;li&gt;No lifecycle policies&lt;/li&gt;&#10;&lt;li&gt;No replication&lt;/li&gt;&#10;&lt;li&gt;No presigned URLs&lt;/li&gt;&#10;&lt;li&gt;Single account model (account ID: &lt;code&gt;000000000000&lt;/code&gt;)&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/services/sqs/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/services/sqs/</guid><description>&lt;h1 id="sqs-simple-queue-service"&gt;SQS (Simple Queue Service)&lt;a class="anchor" href="#sqs-simple-queue-service"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="overview"&gt;Overview&lt;a class="anchor" href="#overview"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;DevCloud SQS provides in-memory message queues. Queues are stored in memory with thread-safe access (sync.RWMutex). Data is &lt;strong&gt;not persisted&lt;/strong&gt; — all queues and messages are lost on server restart.&lt;/p&gt;&#10;&lt;p&gt;SQS supports dual protocol: legacy Query protocol (form-encoded with XML responses) and modern JSON 1.0 protocol (used by boto3 1.42+). The protocol is auto-detected based on the Content-Type header.&lt;/p&gt;&#10;&lt;h2 id="supported-apis"&gt;Supported APIs&lt;a class="anchor" href="#supported-apis"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;All 23 SQS operations are handled over the JSON 1.0 protocol.&lt;/p&gt;</description></item><item><title/><link>https://skyoo2003.github.io/devcloud/troubleshooting/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://skyoo2003.github.io/devcloud/troubleshooting/</guid><description>&lt;h1 id="troubleshooting"&gt;Troubleshooting&lt;a class="anchor" href="#troubleshooting"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;If your problem isn&amp;rsquo;t here, see &lt;a href="https://github.com/skyoo2003/devcloud/blob/main/SUPPORT.md"&gt;SUPPORT.md&lt;/a&gt; for where to ask.&lt;/p&gt;&#10;&lt;h2 id="build-and-startup"&gt;Build and startup&lt;a class="anchor" href="#build-and-startup"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;code&gt;go: module github.com/skyoo2003/devcloud: Go 1.26 required&lt;/code&gt;&lt;/strong&gt;&#10;Upgrade Go to 1.26+ (&lt;code&gt;go version&lt;/code&gt;, then &lt;a href="https://go.dev/dl/"&gt;go.dev/dl&lt;/a&gt;).&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;code&gt;bind: address already in use&lt;/code&gt; on port 4747&lt;/strong&gt;&#10;Something else holds the port. Change DevCloud&amp;rsquo;s:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# devcloud.yaml&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;server&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;4100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or map a different host port: &lt;code&gt;docker run -p 4100:4747 …&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Server starts but clients get &lt;code&gt;connection refused&lt;/code&gt;&lt;/strong&gt;&#10;Check it is actually listening — any request works, DevCloud has no health&#10;endpoint:&lt;/p&gt;</description></item></channel></rss>