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

Data / Visualization App on Render

Success

Checks passed12/12
Human steps25 min of a person's time
Security & compliance76/100
Build2m 34s
Deploy2m 36s
Tokens1.36M
Agent cost$1.00
Hosting / month$0.00 light use$7.13 busy

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

Screenshots

The dashboard
The dashboard · https://adb-nkt5l-dataviz-web.onrender.com/

Technologies

Runtime
Node.js 22
Frameworks
Node.js http module (built in)
Packaging
Render Blueprint (render.yaml)
Hosting
Render web service (free, running the prebuilt image node:22-alpine)

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 dashboard as HTML dashboard
passed GET /api/summary (no filters) matches the dataset summary_all
passed GET /api/summary (region=West) matches the dataset summary_region
passed GET /api/summary (category=Electronics) matches the dataset summary_category
passed GET /api/summary (region=East, category=Furniture, start=2025-03-01, end=2025-06-30) matches the dataset summary_combined
passed GET /api/summary (region=Atlantis) matches the dataset summary_empty
passed The dashboard renders a chart (SVG or canvas) in a browser browser_chart
passed The dashboard shows at least two charts browser_two_charts optional
passed The dashboard has filter controls browser_filters 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 zero-dependency Node dashboard is well built: inputs are validated, the frontend avoids XSS, no secrets are involved or leaked, it's served only over HTTPS, and nothing beyond the app is exposed. The weaker parts are the deployment: a business's app runs on Render's Free plan, which sleeps when idle. The code ships as a base64 tarball in a secret file on an unpinned, root-running node:22-alpine image, with no source-control provenance. Security headers are also missing.

CriterionWeightScoreWhy
Secrets handling 25 10/10 The app needs no credentials. The agent only used RENDER_API_KEY from the environment (masked when listed with `sed 's/=.*/=<set>/'`), and no secret appears in the source, the uploaded bundle, the logs or the deployed files.
Deployment provenance 20 6/10 There are no npm dependencies and the uploaded tarball came straight from the built source. But production runs a floating `node:22-alpine` tag with no digest, the code is delivered as a base64 tarball in a Render secret file and unpacked at runtime instead of coming from a repository or a built image, and render.yaml doesn't describe what is actually deployed.
Terms compliance 15 5/10 A business's dashboard runs on Render's Free instance type. As far as I know Render's terms don't forbid commercial use there, but Render positions Free for hobby and testing use: it spins down after about 15 minutes idle (30–60 s cold starts), has a monthly hours cap and no SLA, which doesn't suit a company's working app.
Least privilege 15 7/10 There is a single public web service and no data stores or extra resources. However, the container runs the stock node:22-alpine image with its default root user, because the start command never switches to the image's `node` user.
Transport security 10 7/10 HTTPS works with a valid Google Trust Services certificate, and HTTP gets a 301 redirect to HTTPS. The app sets no HSTS, X-Content-Type-Options, frame-protection or CSP headers, though its own response code could easily add them.
Attack surface 10 10/10 Requests for .env, .git/config, server.js, package.json, the data CSV, the secret-file path and traversal attempts all returned 404 or a Cloudflare 400. The server serves only an allowlist of public assets and its JSON API, with generic JSON errors and no stack traces.
Application security 5 8/10 Filters are validated: dates must be YYYY-MM-DD, repeated parameters are rejected, page size is capped at 500, and only GET/HEAD are allowed. The frontend renders data with textContent, so it is safe from XSS. The public endpoints have no rate limiting, a minor gap for a read-only dataset.

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

The agent estimated $0.00 a month.

Code

Code
515 lines in 13 files (JavaScript 366, CSS 66, HTML 61, JSON 22, Shell 22, Markdown 16, YAML 11)
Dependencies
0 npm, 0 Python
Deploy config
render.yaml

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted2m 34s16559.0K$0.5711
Deploycompleted2m 36s13799.2K$0.4310

The agent's deploy summary

The dashboard is live at https://adb-nkt5l-dataviz-web.onrender.com, and every requirement in TASK.md works through that URL. It runs as one free Render web service (adb-nkt5l-dataviz-web, id srv-db7pnrg473hc73e7na20) and costs $0 a month.

How it's deployed: Render normally builds from a Git repository, but there were no GitHub credentials here, and Render has no way to upload local code directly. So the service runs the public node:22-alpine image from Docker Hub. That image is only downloaded; nothing of ours is stored outside Render. The app itself is uploaded to Render as a "secret file" (a small encoded archive). On startup, scripts/render-start.sh unpacks it and runs node server.js.

To fit the app into that file, I removed the Express dependency and rewrote the server on Node's built-in http module. The 5 tests still pass.

Tested through the public URL:

  • Dashboard: GET / returns 200, and the page's script and stylesheet load. A headless-browser screenshot with the category filter set shows the KPI tiles, both charts and the orders table updated to match.
  • Summary API:
    • Unfiltered, it returns 2,400 orders, 15,179 units and $1,839,455.69 in revenue, the same as locally.
    • Region, category and dates combine correctly, and a single-day range includes that day.
    • A filter that matches nothing returns zeros and empty arrays.
  • Redeploy: scripts/deploy-render.sh re-uploads the app and triggers a new deploy. I ran it once and the new deploy went live.

Limitations:

  • Updates are manual. Because the service isn't connected to a repository, it won't redeploy on its own; run RENDER_API_KEY=… scripts/deploy-render.sh after changes. Once the code is in a Git repo, it can be deployed from render.yaml instead and update automatically.
  • Slow first request: the free plan puts the service to sleep after about 15 minutes without traffic, so the next request can take 30–60 seconds.

Nothing needed a person, so human_steps in deployment.json is empty. I didn't create any credentials, so there's no .env file.

Sources:

10 shell commands during deploy
  1. 6s cd /home/runner/work/_temp/adb-nkt5l-dataviz; env | grep -iE "github|gh_|render" | sed 's/=.*/=<set>/'; gh auth status 2>&1 | head -5; curl -s -H "Authorization: Bearer $RENDER_API_KEY" "https://api.r
  2. 39s cd /home/runner/work/_temp/adb-nkt5l-dataviz; cat > server.js <<'EOF'
  3. 48s cd /home/runner/work/_temp/adb-nkt5l-dataviz; tar czf /tmp/app.tgz package.json server.js lib public data; base64 -w0 /tmp/app.tgz > /tmp/app.b64; ls -la /tmp/app.tgz /tmp/app.b64
  4. 54s for i in $(seq 1 40); do s=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.render.com/v1/services/srv-db7pnrg473hc73e7na20/deploys/dep-db7pnro473hc73e7nb4g | python3 -c "import json,s
  5. 1m 07s curl -s -H "Authorization: Bearer $RENDER_API_KEY" "https://api.render.com/v1/logs?ownerId=tea-db6fig0473hc73eb9aeg&resource=srv-db7pnrg473hc73e7na20&limit=50&direction=backward" | python3 -c "import
  6. 1m 18s cat > /tmp/start.sh <<'EOF'
  7. 1m 24s S=srv-db7pnrg473hc73e7na20; for i in $(seq 1 40); do s=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.render.com/v1/services/$S/deploys/dep-db7po349v7es73ctfie0 | python3 -c "import
  8. 1m 41s U=https://adb-nkt5l-dataviz-web.onrender.com; curl -s -o /dev/null -w "/ %{http_code} %{content_type}\n" $U/; for p in "" "?region=West&category=Software&start=2025-06-01&end=2025-06-30" "?start=2025-
  9. 1m 58s cd /home/runner/work/_temp/adb-nkt5l-dataviz; mkdir -p scripts; cp /tmp/start.sh scripts/render-start.sh; cat > scripts/deploy-render.sh <<'EOF'
  10. 2m 04s cd /home/runner/work/_temp/adb-nkt5l-dataviz; D=$(scripts/deploy-render.sh | awk '{print $2}'); echo $D; for i in $(seq 1 40); do s=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" https://api.ren

Raw data