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 & compliance75/100
Stack fit81/100
Build2m 24s
Deploy2m 30s
Tokens1.66M
Agent cost$1.15
Hosting / month$0.00 light use$7.13 busy

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

Screenshots

The dashboard
The dashboard · https://adb-zvm8n-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

Stack fit

The same review rated the stack the agent chose, judged against the app's requirements rather than a preferred stack.

A zero-dependency Node server with in-memory CSV aggregation and vanilla SVG charts fits this small read-only dashboard well and matches the reasoning in STACK.md. The deployment departed from the planned Git-backed native Node service and runs as an image-backed workaround on a sleeping free instance.

CriterionWeightScoreWhy
Fit for the job 40 9/10 Keeping the read-only 2,400-row CSV in memory is exact and fast, integer-cent sums give correct rounding, and plain fetch plus inline SVG covers the filter, KPI and chart needs without page reloads.
Proportion 30 9/10 One process, the Node standard library only, no database and no build step: about as simple as the requirements allow. The only extra complexity is the secret-file boot shim forced by the delivery method.
Platform fit 30 6/10 A Node web service suits Render, and STACK.md and render.yaml plan for the native runtime. What was deployed instead is an image-backed service that unpacks code from secret files, which works around Render's build pipeline, and it runs on a free instance that sleeps.

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, zero-dependency Node dashboard with careful input validation, an allowlist for static files, and no secrets to leak. Its weaknesses are in the deployment: a commercial app runs on Render's sleeping free tier, the code is shipped as a tarball in a Render secret file on a floating node:22-alpine tag rather than built from an owned repo, and the container runs as root with no security headers.

CriterionWeightScoreWhy
Secrets handling 25 10/10 The app needs no secrets. The Render API key was only read from the environment, and the transcripts never print it (the deploy check prints just 'key-set'). .env is git-ignored and no credentials are in the source or the shipped bundle.
Deployment provenance 20 6/10 What runs is the committed git HEAD, and it has no third-party dependencies. But it is shipped as a base64 tarball in a Render 'secret file' and unpacked at boot, not built from a repo the owner controls, so there is no traceable source-to-build link. The base image is the floating tag node:22-alpine, not pinned to a digest.
Terms compliance 15 4/10 This is a business (commercial) app on Render's free instance type. Render says free instances are for hobby and testing work, not production. They spin down after 15 minutes idle with 30-60 s cold starts, and draw on a capped pool of monthly free hours. The agent noted the sleep but didn't choose a paid Starter plan.
Least privilege 15 7/10 There is one stateless web service with no data store and no extra public resources. The container runs as the node:22-alpine default user (root), because the custom dockerCommand doesn't drop to the image's 'node' user.
Transport security 10 8/10 HTTP returns 301 to HTTPS and the certificate is valid. The app sends none of HSTS, X-Content-Type-Options, X-Frame-Options/frame-ancestors or CSP, though its own server could easily have set them.
Attack surface 10 9/10 Only an explicit allowlist of three static files is served. .env, .git, source, the CSV and the secret bundle all return JSON 404s, and errors return no stack traces. The only extra is a harmless /healthz that reports the row count.
Application security 5 9/10 Dates are strictly validated (400 on bad input), filters are exact-match comparisons in memory with no injection surface, page size is clamped to 1-500 and offset to at least 0, and the client renders all data with textContent. There is no app-level rate limiting, but endpoints are cheap and read-only.

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

The agent estimated $0.00 a month.

Code

Code
636 lines in 15 files (JavaScript 434, CSS 82, HTML 66, Shell 54, Markdown 26, JSON 21, YAML 13)
Dependencies
0 npm, 0 Python
Deploy config
render.yaml

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted2m 24s18607.8K$0.598
Deploycompleted2m 30s11755.8K$0.3810

The agent's deploy summary

The sales dashboard is live at https://adb-zvm8n-dataviz-web.onrender.com, and every TASK.md requirement passes when tested through that public HTTPS address.

What's deployed: one web service, adb-zvm8n-dataviz-web (id srv-db81e8mq1p3s73972p1g), on Render's free plan in Oregon. It costs $0 a month and needs no database.

How it got there: Render normally builds from a Git repository, but there were no GitHub credentials and no repo connected to the Render team. So instead:

  • The service runs the official public Node image, node:22-alpine, which Render pulls itself. I didn't push anything to any registry.
  • The committed app (about 47 KB) is attached to the service as a Render "secret file". The app has no secrets of its own.
  • A small startup script, scripts/render-boot.js, unpacks the app and starts the server.
  • To redeploy the current commit, run scripts/deploy.sh. It updates the files on Render, starts a new deploy, waits until it's live and runs the checks. I ran it once and it worked.
  • If the repo is pushed to GitHub later, render.yaml sets up the normal Git-based deploy instead.

Tests on the public URL:

  • Smoke tests: all 6 checks in scripts/smoke.sh pass. They cover the dashboard page, totals with and without filters (matching the CSV), the empty result, and the orders table.
  • Bad dates: an invalid date gets a 400 response.
  • Browser: in a headless browser, changing filters updated the figures and table without reloading the page, with no page errors.

Limitation: on the free plan the service goes to sleep after about 15 minutes with no traffic. The first request after that takes 30–60 seconds.

Nothing needed a person, so human_steps in deployment.json is empty. I didn't create any new credentials, and .env is excluded from git.

10 shell commands during deploy
  1. 9s cd /home/runner/work/_temp/adb-zvm8n-dataviz; test -n "$RENDER_API_KEY" && echo key-set; gh auth status 2>&1 | head -2; env | grep -iE 'github|gitlab|token' | sed 's/=.*/=<set>/'
  2. 28s cd /home/runner/work/_temp/adb-zvm8n-dataviz; mkdir -p /tmp/bundle; git archive --format=tar.gz -o /tmp/bundle/app.tgz HEAD; ls -l /tmp/bundle/app.tgz; base64 -w0 /tmp/bundle/app.tgz | wc -c; tar tzf
  3. 37s cd /home/runner/work/_temp/adb-zvm8n-dataviz; cat > scripts/render-boot.js <<'EOF'
  4. 50s cd /home/runner/work/_temp/adb-zvm8n-dataviz; timeout 5 docker run --rm -e PORT=10000 -v /tmp/bundle:/etc/secrets:ro node:22-alpine node /etc/secrets/boot.js 2>&1 | tail -8
  5. 58s cd /home/runner/work/_temp/adb-zvm8n-dataviz; python3 - <<'EOF'
  6. 1m 19s cd /tmp/bundle; python3 - <<'EOF' > /tmp/bundle/create.json
  7. 1m 25s for i in $(seq 1 40); do st=$(curl -sS -H "Authorization: Bearer $RENDER_API_KEY" -H "Accept: application/json" "https://api.render.com/v1/services/srv-db81e8mq1p3s73972p1g/deploys?limit=1" | python3
  8. 1m 40s cd /home/runner/work/_temp/adb-zvm8n-dataviz; U=https://adb-zvm8n-dataviz-web.onrender.com; scripts/smoke.sh $U; curl -sS -o /dev/null -w '%{http_code} %{ssl_verify_result}\n' $U/api/summary?start=bad
  9. 2m 02s cd /home/runner/work/_temp/adb-zvm8n-dataviz; cat > scripts/deploy.sh <<'EOF'
  10. 2m 06s cd /home/runner/work/_temp/adb-zvm8n-dataviz; scripts/deploy.sh 2>&1 | uniq | tail -12

Raw data