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

Real-Time Collaborative App on Render

Success

Checks passed13/13
Human steps25 min of a person's time
Security & compliance68/100
Build2m 49s
Deploy2m 34s
Tokens1.12M
Agent cost$0.81
Hosting / month$0.00 light use$7.13 busy

Deployed to https://adb-p9gs9-realtime-web.onrender.com. 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-p9gs9-realtime-web.onrender.com/?room=bench-6045a66c

Technologies

Runtime
Node.js 20+
Frameworks
Node.js http module (built in)
Data
PostgreSQL (Render Postgres, free)
Libraries
wsnode-postgres
Packaging
Render Blueprint (render.yaml)
Hosting
Render web service (free, built from render-examples/express-hello-world)

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

The chat app itself is well built: input is validated, SQL is parameterized, the UI renders safely, nothing sensitive is exposed, and HTTPS is enforced. No secrets leaked. The biggest weakness is provenance: Render builds from a third-party example repo, and the real code arrives as an opaque tarball in a secret file. The free Postgres, which is likely reachable from the internet, expires on 2026-11-12, after which the app will fail to start. Security headers and rate limiting are also missing.

CriterionWeightScoreWhy
Secrets handling 25 9/10 The Render API key and database credentials never appear in the transcripts, source, or the uploaded bundle. DATABASE_URL is a Render service environment variable, and the bundle (built with git archive from an explicit file list) leaves out .env. Minor points: the connection string was set as a literal env var rather than a fromDatabase link, and the external connection string sits in a local .env file.
Deployment provenance 20 4/10 The live service's recorded source is a third-party public repo (render-examples/express-hello-world, unpinned branch main). The real code arrives as an opaque base64 tarball in a Render secret file and is unpacked by a custom build command. What runs can't be traced to any owner-controlled repo or commit. Dependencies are locked with package-lock.json and npm ci, but the Node version is pinned only to the major version.
Terms compliance 15 6/10 Render's free tier is fine for a personal hobby-club app. However, the free Postgres the app depends on expires on 2026-11-12. After that, store.init() will fail at startup and the service will stop working. Spin-down after 15 minutes idle also drops live WebSocket sessions. Both limits were disclosed but not addressed.
Least privilege 15 6/10 The service runs on Render's managed native runtime and the app reads only what it needs. The Postgres database was created through the API without an ipAllowList. Render's default is to accept external connections from any IP (password-protected), even though the app only needs the internal URL.
Transport security 10 7/10 HTTPS works with a valid Google Trust Services certificate, and HTTP returns 301 to HTTPS. The app sets no HSTS, X-Content-Type-Options, frame protection, or CSP, even though it writes its own response headers and could have.
Attack surface 10 9/10 Requests for .env, .git/config, source files, the secret bundle and other paths return the app's JSON 404. Errors are generic, with no stack traces. Only /healthz is extra, and it returns {"ok":true}.
Application security 5 6/10 Input validation is solid: text, user and room lengths are checked, the body is capped at 16 KB, WebSocket payloads at 64 KB, SQL is parameterized, and the UI renders with textContent, so there is no XSS. However, the public endpoints have no rate limiting or connection caps. The per-room cache never evicts, and the WebSocket upgrade doesn'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.
$0.00fixed monthly prices; 0.04 GB out of the Hobby workspace's 5 GB; free instances awake 10 h of 750 free hours
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.13fixed monthly prices; 52.6 GB out of the Hobby workspace's 5 GB, 47.6 GB billed (with a payment method on file; without one Render suspends the services instead); free instances awake 730 h of 750 free hours

Resources the agent created

KindNamePlanList price / monthPricing
serviceadb-p9gs9-realtime-webfree$0.00free x 1 instance(s)
postgresadb-p9gs9-realtime-dbfree$0.00Postgres free

The agent estimated $0.00 a month.

Code

Code
569 lines in 9 files (JavaScript 427, HTML 142, JSON 29, Markdown 20, YAML 18)
Dependencies
2 npm, 0 Python
Deploy config
render.yaml

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted2m 49s14580.8K$0.5311
Deploycompleted2m 34s10538.3K$0.289

The agent's deploy summary

The app is live at https://adb-p9gs9-realtime-web.onrender.com, and every requirement in TASK.md passed when I tested it through that URL. It costs $0 a month and needed no human steps.

What's deployed (both on Render's free plan, Oregon region):

  • Web service adb-p9gs9-realtime-web (srv-db7bvmg473hc73cq8tb0), a native Node service. WebSocket clients connect to wss://adb-p9gs9-realtime-web.onrender.com/ws.
  • Postgres database adb-p9gs9-realtime-db (dpg-db7bv8qj9qps73bru9mg-a), so message history survives restarts. Its connection strings are saved in .env, which is git-ignored.

Tested through the public URL:

  • The page at /?room=... loads.
  • Posting a message returns 201; an empty message or one over 1000 characters returns 400.
  • The history endpoint returns the latest messages, oldest first.
  • Two WebSocket clients sent 20 messages at the same time, and both received all 20 in under 0.4 seconds.
  • A client in a different room received none of those messages.
  • An invalid WebSocket message got an error reply.
  • The Server-Sent Events stream delivered a posted message.

How the code got there: there were no GitHub credentials, so I couldn't push a repository for Render to build from. Instead, the service builds from Render's public example repo (render-examples/express-hello-world). Its build step replaces that repo's contents with this app, which I uploaded to Render as a packed "secret file" called app.b64. Everything stays on Render, but redeploying is manual: repack the code, update that file through the Render API, and start a deploy. If a connected Git repo becomes available later, render.yaml describes the same setup.

Free-tier limits:

  • The web service sleeps after about 15 minutes with no traffic. The first request after that takes about a minute, and open connections drop; the page reconnects on its own.
  • Render's free Postgres expires 30 days after creation unless it is upgraded.
  • The service must stay at one instance, because messages are passed between users inside a single server process.

deployment.json is written. I added it and .env to .gitignore, and committed the app locally.

9 shell commands during deploy
  1. 5s env | cut -d= -f1 | grep -iE 'render|git|gh_|token' ; git remote -v; git log --oneline | head; curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.render.com/v1/owners | head -c 600; echo;
  2. 15s gh auth status 2>&1 | head -3; ls ~/.config/gh 2>&1; git config --global --list 2>&1 | head
  3. 26s printf '.env\ndeployment.json\n' >> .gitignore && git add -A && git commit -qm "Chat rooms app
  4. 32s git archive --format=tar.gz HEAD package.json package-lock.json server.js store.js public | base64 -w0 > /tmp/app.b64 && wc -c /tmp/app.b64
  5. 1m 21s python3 - <<'EOF'
  6. 1m 26s for i in $(seq 1 40); do s=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.render.com/v1/services/srv-db7bvmg473hc73cq8tb0/deploys/dep-db7bvmo473hc73cq8udg | python3 -c 'import json,s
  7. 2m 06s U=https://adb-p9gs9-realtime-web.onrender.com
  8. 2m 16s NODE_PATH=$PWD/node_modules node /tmp/remote.js
  9. 2m 27s cat > deployment.json <<'EOF'

Raw data