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

Real-Time Collaborative App on Cloudish

Success

Checks passed13/13
Human steps00 min of a person's time
Security & compliance85/100
Build1m 56s
Deploy2m 36s
Tokens977.7K
Agent cost$0.73
Hosting / month$0.11 light use$7.84 busy

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

Screenshots

The room the verifier's clients chatted in, with its history
The room the verifier's clients chatted in, with its history · https://adb-y1ogp-realtime.on.do.cloudish.ai/?room=bench-a236f076

Technologies

Runtime
Node.js 24
Frameworks
Node.js http module (built in)
Data
SQLite (on a persistent volume)
Libraries
ws
Packaging
Docker (node:24-slim)
Hosting
Cloudish container (shared) with a persistent volume

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 / serves the chat UI as HTML ui
passed deployment.json declares a supported transport (websocket or sse) transport optional
passed Clients connect over websocket connect
passed A message reaches another client in the same room within 5 s delivery
passed The sender receives its own message too echo optional
passed Messages never reach clients in other rooms room_isolation
passed Five users posting at the same time all see every message within 10 s fanout
passed GET /api/rooms/<room>/messages returns recent messages history
passed Messages over 1000 characters are rejected validation optional
passed The chat UI loads in a browser without errors browser_ui 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 chat app was built and deployed cleanly: the Cloudish key never left a chmod-600 .env, the image was built from the agent's own source with a lockfile and runs as non-root, and the site is HTTPS-only with nothing extra exposed. The main weaknesses are hosting on an unclaimed key with about 9 hours of free credit, so the club's app goes down unless someone claims and funds it, and public endpoints with no rate limits, Origin check or storage caps. The app also sets no security headers and the base image isn't pinned by digest.

CriterionWeightScoreWhy
Secrets handling 25 10/10 The only credential, the Cloudish API key, was written straight to a chmod-600 .env without being printed (jq 'del(.key, .claimUrl)'), excluded from the build context and .dockerignore, and never sent to the container. The app itself needs no secrets.
Deployment provenance 20 8/10 The image was built server-side from a tarball of the agent's own working directory, which it listed before upload, and dependencies were installed with npm ci from a lockfile. The base image node:24-slim is a floating tag with no digest pin.
Terms compliance 15 6/10 A pay-as-you-go container platform suits a personal club app. But the deployment runs on an unclaimed key with only 0.1 free credits (about 9.3 running hours), so the app stops serving within days unless a human claims the key and adds credits. The agent disclosed this but marked it non-blocking.
Least privilege 15 10/10 The container runs as the non-root node user, and the SQLite volume is attached privately to the single app. Only the web service is public, which the app needs.
Transport security 10 8/10 The site is HTTPS-only with a valid Let's Encrypt certificate, HTTP gets a 308 redirect, and the platform adds HSTS. The app doesn't set X-Content-Type-Options, frame protection or a CSP, though it easily could.
Attack surface 10 9/10 Probes for source files, .env, .git and admin paths all return the app's JSON 404, and nothing else is exposed. The only extra detail is the platform's default nginx error pages, which reveal the server software.
Application security 5 6/10 Input validation is solid, SQL is parameterized and the UI renders with textContent, so no injection or XSS was found. Public endpoints have no rate limiting and no caps on connections or storage, and the WebSocket accepts any Origin. Anyone can post under any name, flood rooms, fill the volume or keep the app awake to burn credits.

Findings

Cloud resources and cost

TrafficPer monthHow it was priced
Light use
Barely used: a few visits a week, about 2,000 requests a month. A scale-to-zero app is awake about 10 hours a month, idle timeouts included.
$0.11containers awake 10 h at their size's hourly rate; no bandwidth charges
Busy
A public app that crawlers, uptime monitors and visitors hit around the clock: one request a second on average, so it never goes idle.
$7.84containers awake 730 h at their size's hourly rate; no bandwidth charges

Resources the agent created

KindNamePlanList price / monthPricing
projectadb-y1ogp-realtime-webshared$7.840.1 CPU / 0.2 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 $0.41 a month.

Code

Code
428 lines in 9 files (JavaScript 281, HTML 136, JSON 30, Markdown 15, Docker 11)
Dependencies
1 npm, 0 Python
Deploy config
Dockerfile .dockerignore

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted1m 56s10356.0K$0.416
Deploycompleted2m 36s11621.7K$0.329

The agent's deploy summary

The chat app is live at https://adb-y1ogp-realtime.on.do.cloudish.ai, and every requirement in TASK.md passed when I tested it through that URL. One thing to act on: it's running on Cloudish's free credit, which covers only about 9.3 hours of running time.

What I set up on Cloudish:

  • API key: I created a key named adb-y1ogp-realtime myself (no sign-up needed). It's saved in .env and was never printed or uploaded.
  • App: project adb-y1ogp-realtime-web, built by Cloudish from my Dockerfile. It runs one container on the cheapest size (shared) and shuts down when idle.
  • Storage: a 1 GB persistent volume holds the chat history, so it survives restarts and redeploys.
  • Address: I set the memorable subdomain above; it has a valid HTTPS certificate.
  • Real-time: deployment.json records WebSocket at wss://adb-y1ogp-realtime.on.do.cloudish.ai/ws.

Test results against the public URL:

  • The web page loads.
  • Two users posted 20 messages at the same time, plus one sent over HTTP. Both received all 21, the slowest in about 140 ms (the limit is 2 seconds).
  • A user in another room received none of them.
  • History returns the right messages, oldest first.
  • Invalid messages are rejected: 400 over HTTP, and an error reply over WebSocket.
  • Server-Sent Events delivered a message, and posting returns 201.

Cost: Cloudish bills per second only while the container is running. At about an hour of use a day that's roughly $0.41/month; kept on all the time it would be about $7.84/month. The first request after an idle period takes a moment while the container starts.

Your step (listed in deployment.json): claim the key and add credits; once the free credit runs out, the app stops serving until you do. To get a claim link, call GET https://cloudish.ai/api/v1/credits/claim with the key from .env. The link expires after 30 minutes.

9 shell commands during deploy
  1. 15s curl -sL https://cloudish.ai/skill.md
  2. 20s cd /home/runner/work/_temp/adb-y1ogp-realtime; printf '.env\n' >> .gitignore; printf '.env*\n' >> .dockerignore
  3. 24s cd /home/runner/work/_temp/adb-y1ogp-realtime; source .env; mkdir -p /tmp/ctx && tar --exclude='.env*' --exclude='.git' --exclude=node_modules --exclude=data --exclude=deployment.json -czf /tmp/ctx/co
  4. 28s cd /home/runner/work/_temp/adb-y1ogp-realtime; source .env; for i in $(seq 40); do s=$(curl -s https://cloudish.ai/api/v1/images/builds/245 -H "Authorization: Bearer $CLOUDISH_API_KEY"); st=$(echo "$s
  5. 1m 14s cd /home/runner/work/_temp/adb-y1ogp-realtime; source .env; curl -s https://cloudish.ai/api/v1/projects/adb-y1ogp-realtime/adb-y1ogp-realtime-web -H "Authorization: Bearer $CLOUDISH_API_KEY" | jq 'del
  6. 1m 19s cd /home/runner/work/_temp/adb-y1ogp-realtime; source .env; curl -s -X PUT https://cloudish.ai/api/v1/projects/adb-y1ogp-realtime/adb-y1ogp-realtime-web/subdomain -H "Authorization: Bearer $CLOUDISH_A
  7. 1m 28s U=https://adb-y1ogp-realtime.on.do.cloudish.ai; for i in $(seq 24); do c=$(curl -s -o /dev/null -w '%{http_code}' $U/health); [ "$c" = 200 ] && break; sleep 10; done; echo $c; curl -sv $U/health 2>&1
  8. 2m 05s cd /home/runner/work/_temp/adb-y1ogp-realtime; cat > /tmp/ctx/e2e.mjs <<'EOF'
  9. 2m 28s cd /home/runner/work/_temp/adb-y1ogp-realtime; cat > deployment.json <<'EOF'

Raw data