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

Static Content Site on Render

Success

Checks passed16/16
Human steps25 min of a person's time
Security & compliance75/100
Build1m 14s
Deploy2m 17s
Tokens694.0K
Agent cost$0.53
Hosting / month$0.00 light use$7.13 busy

Deployed to https://adb-t3gz2-static-web.onrender.com. Every deployment is deleted after it's verified and reviewed.

Screenshots

The home page
The home page · https://adb-t3gz2-static-web.onrender.com/
The contact page after the verifier submitted the form
The contact page after the verifier submitted the form · https://adb-t3gz2-static-web.onrender.com/contact

Technologies

Runtime
Node.js 18+
Frameworks
Node.js http module (built in)
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 / 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

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 with tight allowlist routing, solid input validation, HTTPS with an HTTP redirect, nothing exposed beyond the app, and no secrets mishandled. The main weaknesses are in how it was deployed. Render builds from an unpinned third-party example repo, while the code that actually runs comes from a base64 tarball in an env var, so provenance is weak. A commercial site is also running on a free instance that sleeps when idle. The app also sets no security headers.

CriterionWeightScoreWhy
Secrets handling 25 10/10 The app needs no secrets. The Render API key was only ever used as $RENDER_API_KEY in curl headers and never printed; the env listing in the transcript shows only variable names. No credentials are in the source, the bundle or the deployed files.
Deployment provenance 20 4/10 The service's git source is a third-party public repo (render-examples/express-hello-world, branch main, not pinned to a commit) that the owner doesn't control. The code actually running is an unversioned base64 tarball stuffed into an env var, so Render's deploy record points at a commit unrelated to what runs. The app itself has zero dependencies, which keeps the supply-chain risk low.
Terms compliance 15 5/10 A business's marketing site is hosted on Render's free instance type. Render's terms don't ban commercial use as far as I know, but Render positions free instances for hobby and testing use. They spin down after about 15 minutes idle, so visitors wait 30-60s on a cold start, and they come with no uptime guarantees. That's a poor fit for a commercial site that should always be up.
Least privilege 15 9/10 There is one managed Node web service, no data stores and no extra public resources. The process runs on Render's managed runtime, which the agent can't configure. The only gap is that the app bundle sits in an env var instead of a repo.
Transport security 10 7/10 Served over HTTPS with a valid certificate, and HTTP gets a 301 redirect to HTTPS. The Node server sets no HSTS, X-Content-Type-Options, frame protection or CSP headers, though it easily could.
Attack surface 10 10/10 Only allowlisted pages and assets are served. Probes for .env, .git/config, server.js, package.json, the test files and path traversal all returned 404 or 400, with no stack traces or listings.
Application security 5 8/10 The contact endpoint checks types and lengths, validates email, caps the body at 20 KB and handles bad JSON cleanly, and the client renders responses with textContent. Nothing limits how often the endpoint can be called, but submissions aren't stored or sent anywhere, so abuse has little effect.

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-t3gz2-static-webfree$0.00free x 1 instance(s)

The agent estimated $0.00 a month.

Code

Code
352 lines in 13 files (JavaScript 163, HTML 160, CSS 29, JSON 22, YAML 8, Markdown 5)
Dependencies
0 npm, 0 Python
Deploy config
render.yaml

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted1m 14s8291.3K$0.307
Deploycompleted2m 17s9402.7K$0.238

The agent's deploy summary

The site is live at https://adb-t3gz2-static-web.onrender.com, and every requirement in TASK.md works through that public URL.

What's deployed: one Render web service, adb-t3gz2-static-web (srv-db7paktg1s2s73bc2da0), on the free plan. Monthly cost is $0. I didn't create any credentials, so there's no .env.

What I checked on the public URL:

  • Pages: /, /about and /contact return 200 with text/html, a title, a viewport tag and navigation to the other pages. Each has the required heading or form fields.
  • 404s: unknown paths, including /about.html, return 404.
  • Contact endpoint: POST /api/contact returns {"ok":true} for valid input. A missing name, bad email or empty message each return 400 with an error message.
  • Browser test: headless Chrome at a phone-sized screen filled in and sent the form. The confirmation appeared and the page did not reload.

Unusual setup: Render deploys from a git repo, and there were no GitHub credentials here, so I couldn't push the code anywhere.

  • How it works now: the service is built from Render's public example repo (render-examples/express-hello-world), which is only used as a starting point. The build step unpacks this app from a compressed copy stored in an environment variable (APP_BUNDLE_B64), runs its tests, and then starts it. Nothing runs outside Render.
  • Shipping changes: automatic deploys are off. To update the site, rebuild that compressed copy, update the variable, and start a deploy.

Human step (not blocking): I listed one in deployment.json. Someone needs to push the code to a GitHub repo, connect it to Render and point the service at it, then delete APP_BUNDLE_B64. That gives normal deploys from git.

Limitation: free instances go to sleep after about 15 minutes with no traffic. The first request after that can take 30–60 seconds.

8 shell commands during deploy
  1. 6s env | cut -d= -f1 | grep -iE 'token|key|gh|git|render'; gh auth status 2>&1 | head -5; curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.render.com/v1/owners | head -c 600
  2. 19s curl -s -H "Authorization: Bearer $RENDER_API_KEY" "https://api.render.com/v1/services?limit=50" | python3 -c "import json,sys; [print(s['service']['name'],s['service']['type'],s['service'].get('repo'
  3. 31s tar czf /tmp/app.tgz server.js package.json public && B=$(base64 -w0 /tmp/app.tgz) && echo ${#B} &&
  4. 39s S=srv-db7paktg1s2s73bc2da0 && H=(-H "Authorization: Bearer $RENDER_API_KEY" -H 'Content-Type: application/json') &&
  5. 44s S=srv-db7paktg1s2s73bc2da0; H=(-H "Authorization: Bearer $RENDER_API_KEY" -H 'Content-Type: application/json')
  6. 1m 50s U=https://adb-t3gz2-static-web.onrender.com
  7. 1m 58s mkdir -p /tmp/pw && cd /tmp/pw && npm init -y >/dev/null && npm i playwright@1 >/dev/null 2>&1 && npx playwright install chromium >/dev/null 2>&1 && cat > t.js <<'EOF'
  8. 2m 09s cat > deployment.json <<'EOF'

Raw data