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

Real-Time Collaborative App on DigitalOcean

Success

Checks passed13/13
Human steps37 min of a person's time
Security & compliance88/100
Build1m 58s
Deploy1m 44s
Tokens758.8K
Agent cost$0.60
Hosting / month$5.00 light use$5.00 busy

Deployed to https://adb-wf7uo-realtime-5cs45.ondigitalocean.app. 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-wf7uo-realtime-5cs45.ondigitalocean.app/?room=bench-120fb91a

Technologies

Runtime
Node.js 22
Frameworks
Node.js http module (built in)
Libraries
ws
Packaging
Docker (node:22-alpine)App spec (.do/app.yaml)
Hosting
App Platform service (apps-s-1vcpu-0.5gb)DigitalOcean Container Registry (starter)

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

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).

A small, carefully built Node/ws chat app on a paid DigitalOcean App Platform Basic instance. The app needs no secrets, the container runs as non-root, nothing beyond the app is exposed, HTTPS is enforced, and the hosting fits personal use. The main weaknesses are provenance (an unpinned base image, a mutable v1 image tag, and builds pushed from the agent's local workspace), plus minor app-level gaps: no security headers, no rate limiting, unbounded in-memory room creation, and no Origin check on WebSocket upgrades.

CriterionWeightScoreWhy
Secrets handling 25 10/10 The app needs no secrets and none were created. The DigitalOcean token was only referenced as $DIGITALOCEAN_ACCESS_TOKEN in deploy commands and never printed, and no credentials appear in the source, the image or the app spec.
Deployment provenance 20 6/10 The image was built from the local workspace and pushed to the owner's private DOCR, so production runs the code that was built. But the base image is an unpinned tag (node:22-alpine), the app spec deploys a mutable tag (v1) instead of a digest, there's no source repository or CI, and doctl was downloaded with no checksum check.
Terms compliance 15 10/10 The app is for personal use. It runs on a paid App Platform Basic instance ($5/month), which doesn't sleep or expire, and uses the free DOCR Starter tier for its single ~61 MB repository, which is within that tier's limits. As far as I know, DigitalOcean's terms allow this use.
Least privilege 15 10/10 The container runs as the non-root node user. The registry is private, there's no data store, and the only public resource is the single App Platform service.
Transport security 10 8/10 The app is served over HTTPS with a valid Google Trust Services certificate (valid to Dec 22, 2026), and HTTP returns a 301 redirect to HTTPS. The app sets no HSTS, X-Content-Type-Options, frame-protection or CSP headers, though it could easily have done so.
Attack surface 10 10/10 Probes for .env, .git, source files, the Dockerfile and admin paths all return a generic JSON 404. Errors return no stack traces, and the only extra endpoint is a harmless /health.
Application security 5 7/10 Input validation is solid: room-name regex, message and name length limits, a body-size cap, a WebSocket maxPayload and safe JSON errors. The UI renders with textContent, so there's no XSS. However, the app has no rate limiting, any request can create a new in-memory room without limit, and WebSocket upgrades don't check the Origin header.

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.
$5.00fixed monthly prices; 0.0373 GiB out of a 50 GiB allowance
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.
$5.00fixed monthly prices; 49 GiB out of a 50 GiB allowance

Resources the agent created

KindNamePlanList price / monthPricing
appadb-wf7uo-realtimeadb-wf7uo-realtime-web: apps-s-1vcpu-0.5gb x 1$5.00adb-wf7uo-realtime-web: apps-s-1vcpu-0.5gb x 1
registryadb-wf7uo-realtimestarter$0.00Container Registry starter tier (one per account)

The agent estimated $5.00 a month.

Code

Code
486 lines in 10 files (JavaScript 345, HTML 130, JSON 29, Markdown 16, YAML 16, Docker 11)
Dependencies
1 npm, 0 Python
Deploy config
Dockerfile .dockerignore .do/app.yaml

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted1m 58s12423.8K$0.428
Deploycompleted1m 44s7335.0K$0.186

The agent's deploy summary

The chat app is live at https://adb-wf7uo-realtime-5cs45.ondigitalocean.app over HTTPS, and every requirement in TASK.md worked when I tested it through that URL.

What I deployed (about $5/month):

  • Container registry: adb-wf7uo-realtime on the free starter tier, in nyc3. I built the Docker image locally and pushed it there as adb-wf7uo-realtime-web:v1.
  • App Platform app: adb-wf7uo-realtime (id d1340407-bcac-4f7c-8ded-82851d8e8b53). It runs one instance of the smallest paid size, apps-s-1vcpu-0.5gb, which costs $5/month. DigitalOcean provides the HTTPS certificate, and the health check uses /health. The app configuration is saved in .do/app.yaml.

What I tested on the public URL:

  • The web UI returns 200.
  • Posting a message over HTTP returns 201; empty text and text over 1000 characters both return 400.
  • The history endpoint returns the room's messages in the expected shape.
  • WebSocket (wss://…/ws): four clients sent 20 messages at the same time, and every client received all 20 within 60 ms. An invalid message got an error reply, and a client in another room received nothing.
  • Server-Sent Events: the stream delivered a posted message.

deployment.json is written, with realtime set to WebSocket at wss://adb-wf7uo-realtime-5cs45.ondigitalocean.app/ws. Nothing needed a person, so human_steps is empty. I didn't create any credentials, so there's no .env file; I added .env to .gitignore anyway.

Limitation: message history is kept in memory. It's wiped on every redeploy or restart, and the app has to stay at one instance, because a second instance wouldn't share rooms with the first.

6 shell commands during deploy
  1. 10s git diff --no-index /dev/null server.js | head -0; grep -n "MAX_ROOM\|module.exports" server.js; which doctl; curl -s -H "Authorization: Bearer $DIGITALOCEAN_ACCESS_TOKEN" https://api.digitalocean.com
  2. 14s cd /tmp && curl -sL https://github.com/digitalocean/doctl/releases/download/v1.146.0/doctl-1.146.0-linux-amd64.tar.gz | tar xz && sudo mv doctl /usr/local/bin/ && doctl version && doctl registry optio
  3. 18s doctl registry create adb-wf7uo-realtime --subscription-tier starter --region nyc3 && doctl registry login --expiry-seconds 3600 >/dev/null && docker build -q --platform linux/amd64 -t registry.digita
  4. 40s mkdir -p .do && cat > .do/app.yaml <<'EOF'
  5. 1m 23s U=https://adb-wf7uo-realtime-5cs45.ondigitalocean.app
  6. 1m 37s echo ".env" >> .gitignore && doctl registry get -o json | python3 -c "import sys,json;print(json.load(sys.stdin))" 2>/dev/null | head -c 300; echo; cat > deployment.json <<'EOF'

Raw data