Cloudish · Opus 5.5 · medium effort · HIPAA organization · trial 1

Static Content Site on Cloudish

Success

Checks passed16/16
Human steps00 min of a person's time
Security & compliance83/100
Build1m 18s
Deploy3m 38s
Tokens726.0K
Agent cost$0.52
Hosting / month$21.66 always on

Deployed to https://adb-l0oek-static-web.on.do.cloudish.ai. Every deployment is deleted after it's verified and reviewed.

Technologies

Runtime
Node.js 22
Frameworks
Node.js http module (built in)
Packaging
Docker (node:22-alpine)
Hosting
Cloudish container (small)

Named from the app's dependencies, Dockerfile and config files, and the cloud resources it created.

Checks

Black-box checks against the live URL. A cell succeeds when every required check passes. The app's spec

ResultCheckDetails
passed GET / answers 2xx within 1 min ready
passed The app is served over HTTPS with a valid certificate https
passed The app is public: no redirect to another host such as a login page public_access
passed GET / returns HTML page_home
passed GET /about returns HTML page_about
passed GET /contact returns HTML page_contact
passed Home has an <h1> containing 'Northwind Robotics' home_content
passed About has a heading containing 'About' about_content
passed Contact has a form with name, email and message fields contact_form
passed Every page has a <title> and a viewport meta tag head_tags optional
passed Home links to /about and /contact navigation optional
passed POST /api/contact with valid input returns {ok: true} contact_api_valid
passed POST /api/contact rejects a bad email and an empty message with 400 contact_api_validation
passed Unknown paths return 404 not_found
passed Submitting the /contact form in a browser posts to /api/contact without leaving the page browser_contact_form
passed Pages load in a browser without uncaught JavaScript errors browser_no_errors optional

Human steps

None: the agent got everything it needed on its own.

Security & compliance review

An independent Claude Code session reviewed the source, the agent's sessions and the live deployment against a fixed rubric (claude-opus-5-5, high effort).

The Northwind Robotics site is a small, dependency-free Node server running as a non-root user. It serves only allowlisted routes over valid HTTPS with an HTTP redirect and HSTS, and the API key was kept out of the build context and every deployed file. The weaknesses are minor: no CSP or frame-protection headers, no rate limiting on /api/contact, a base image not pinned to a digest, and a platform CORS layer that echoes back any origin.

CriterionWeightScoreWhy
Secrets handling 25 10/10 The Cloudish API key was written straight to .env without being echoed, and both the upload tarball (--exclude='.env*') and .dockerignore leave it out. The app itself needs no secrets, and no credential shows up in the source, the image or any live response.
Deployment provenance 15 7/10 The agent's own local sources were uploaded as a tarball and built server-side from the Dockerfile in app/, and there are no npm dependencies. The base image node:22-alpine is a floating tag, not pinned to a digest.
Transport security 15 6/10 HTTPS uses a valid Let's Encrypt certificate, HTTP gets a 308 redirect to HTTPS, and HSTS is set. There is no Content-Security-Policy and no frame protection (X-Frame-Options or frame-ancestors), and the JSON responses lack nosniff.
Attack surface 15 9/10 The server answers only on an allowlist of routes, so source files, .env, .git, Dockerfile and TASK.md all return 404, and path traversal is rejected. The only extras are a harmless /healthz endpoint and a platform-level CORS layer that echoes back any Origin with credentials allowed.
Application security 20 8/10 Input is validated strictly for type, email format and non-empty fields. Bodies over 64 KB get a 413, bad JSON gets a clean 400, and the client renders messages with textContent, so there is no XSS path. /api/contact has no rate limiting or per-field length limits, and it accepts cross-origin submissions.
Least privilege 10 9/10 The container runs as the non-root 'node' user, there is no data store or volume, and only one service is public, which this public site needs. The API key is an unclaimed anonymous account.

Findings

Cloud resources and cost

Resources the agent created

KindNamePlanList price / monthPricing
projectadb-l0oek-static-websmall$21.660.5 CPU / 1 GB x 1 replica(s) running 730 h/month (live GET /api/v1/pricing); billed per second and scales to zero when idle, so idle apps cost less

The agent estimated $7.84 a month.

Code

Code
282 lines in 13 files (JavaScript 173, HTML 88, JSON 24, CSS 13, Docker 8)
Dependencies
0 npm, 0 Python
Deploy config
Dockerfile .dockerignore

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted1m 18s6185.1K$0.254
Deploycompleted3m 38s11541.0K$0.279

The agent's deploy summary

The Northwind Robotics site is live at https://adb-l0oek-static-web.on.do.cloudish.ai, and everything in TASK.md works through that URL. The catch is credits: it's running on a free grant of only 0.1 credits, so it will stop serving once that runs out unless someone adds more.

What I deployed

  • I created a Cloudish API key named adb-l0oek-static through the API; no signup was needed. The key is saved in .env, and I added .env to .gitignore.
  • Cloudish built the existing Dockerfile on its own servers and deployed it as one container app, adb-l0oek-static-web (project id 82). It uses the default shared size and shuts down after a period with no traffic.
  • I gave it a readable subdomain in place of the random one it was assigned.

What I tested through the public URL

  • /, /about and /contact return 200 text/html, each with a <title>, the viewport tag and links to the other pages.
  • The home page has the "Northwind Robotics" <h1>, and the contact page has the name, email and message fields and a submit button.
  • Unknown paths, and the pages with an .html suffix, return 404.
  • POST /api/contact returns 200 {"ok":true} for valid input. It returns 400 with an error for a missing name, an invalid email or an empty message.
  • In a headless Chrome test, submitting the contact form showed the confirmation without reloading the page.

What didn't go smoothly

  • Credits: the balance after deploying was about 0.097 credits. At most $7.84 a month if it ran all day; actual cost will be lower because it shuts down when idle. When the credits run out, visitors get a 402 or 503 page. Adding more requires a person to claim the key and add credits, which I listed under human_steps in deployment.json. That step isn't blocking yet.
  • First request after a quiet spell: because the app shuts down when idle, that first request can take a few seconds while it starts.
  • Initial start: the cluster reported it was short on capacity when the app first started. It came up on its own within about a minute.
9 shell commands during deploy
  1. 14s curl -s https://www.cloudish.ai/skill.md
  2. 18s ls -a; printf '.env\ncontext.tar.gz\nnode_modules\n' > .gitignore
  3. 22s set -a && . ./.env && set +a && tar --exclude='.env*' --exclude='.git' --exclude='context.tar.gz' -czf /tmp/context.tar.gz . && curl -s -X POST https://cloudish.ai/api/v1/projects -H "Authorization: B
  4. 26s . ./.env && for i in $(seq 40); do s=$(curl -s https://cloudish.ai/api/v1/images/builds/220 -H "Authorization: Bearer $CLOUDISH_API_KEY" | python3 -c 'import sys,json;b=json.load(sys.stdin)["build"];p
  5. 1m 22s . ./.env && curl -s -X PUT https://cloudish.ai/api/v1/projects/adb-l0oek-static/adb-l0oek-static-web/subdomain -H "Authorization: Bearer $CLOUDISH_API_KEY" -H "content-type: application/json" -d '{"la
  6. 2m 53s U=https://adb-l0oek-static-web.on.do.cloudish.ai; for p in / /about /contact /style.css /contact.js /nope /about.html; do curl -s -o /tmp/b -w "$p %{http_code} %{content_type}\n" $U$p; done; curl -s $
  7. 3m 03s mkdir -p /tmp/pw && cd /tmp/pw && npm init -y >/dev/null && npm i -s puppeteer-core >/dev/null 2>&1; CH=$(which google-chrome chromium chromium-browser 2>/dev/null | head -1); echo $CH; cat > t.js <<'
  8. 3m 22s . ./.env && curl -s https://cloudish.ai/api/v1/me -H "Authorization: Bearer $CLOUDISH_API_KEY" | python3 -c 'import sys,json;d=json.load(sys.stdin);k=d.get("apiKey",d);print({x:k.get(x) for x in ("ali
  9. 3m 30s cat > deployment.json <<'EOF'

Raw data