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

Data / Visualization App on Vercel

Success

Checks passed12/12
Human steps25 min of a person's time
Security & compliance74/100
Build2m 30s
Deploy1m 23s
Tokens1.29M
Agent cost$0.84
Hosting / month$20.00 light use$20.00 busy

Deployed to https://adb-9eaes-dataviz-web.vercel.app. Every deployment is deleted after it's verified and reviewed.

Screenshots

The dashboard
The dashboard · https://adb-9eaes-dataviz-web.vercel.app/

Technologies

Runtime
Node.js 20+
Frameworks
Plain Vercel Functions
Packaging
vercel.json
Hosting
Vercel project (node)Vercel Functions

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 on Vercel is well built: it needs no secrets, serves only public/ (source, .env, .git and the raw CSV all return 404), escapes all dynamic HTML, and validates its query parameters. It is served over HTTPS with HSTS. The main problem is compliance: a company's commercial app is hosted on a Vercel Hobby team, and Hobby allows only personal, non-commercial use. Smaller issues are a CLI deploy from a local directory with no git provenance, an unpinned CLI, missing CSP and frame headers, a .env.local the agent didn't add to .vercelignore until after the first deploy, and no rate limiting.

CriterionWeightScoreWhy
Secrets handling 25 9/10 The app needs no secrets. The Vercel token was read from environment variables ($VERCEL_TOKEN) and never written to files or printed. One minor gap: `vercel link` created a .env.local (probably holding a VERCEL_OIDC_TOKEN), and the first production deploy ran before .env.local was added to .vercelignore. The CLI's default ignore list most likely excluded it, and it was never publicly reachable.
Deployment provenance 20 7/10 The CLI uploaded the deployment from the agent's local working directory. Nothing goes through a git repository the owner controls, so production can't be traced to a commit. The app has zero npm dependencies, but the Vercel CLI was installed as vercel@latest without a pinned version, and the Node runtime is only bounded by engines ">=20".
Terms compliance 15 2/10 This is a commercial app (a company's sales dashboard), but the Vercel team is on the Hobby plan. Vercel's Hobby terms allow only personal, non-commercial use, so this hosting breaks the provider's terms. The agent also didn't notice or flag the plan.
Least privilege 15 9/10 The setup has no database or other public resources. The CSV ships inside the function bundles and isn't served statically. Per-deployment URLs stay behind Vercel's default Deployment Protection, and only the production alias is public. The company's order-level sales data can be read by anyone, but the task's spec requires that.
Transport security 10 8/10 The site is HTTPS-only: HTTP returns a 308 redirect to HTTPS, and the platform sends HSTS with preload. The app doesn't set X-Content-Type-Options, frame protection or a CSP, which it could have done through vercel.json headers.
Attack surface 10 9/10 Requests for source files, .env, .env.local, .git, .vercel, the CSV, package.json and tests all return 404, and there are no debug endpoints. /_src redirects to Vercel's source viewer, which requires authentication.
Application security 5 8/10 Filters use exact matching on in-memory data, so there is nothing to inject into. Dates are checked against a regex, and limit/offset are clamped to 1..200. All dynamic HTML is escaped. Minor issues: invalid calendar dates such as 2025-02-31 are accepted, any HTTP method is accepted, and only Vercel's platform defaults protect the endpoints from abuse.

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.
$20.00Hobby is for non-commercial use only, so priced on Pro: $20 platform fee including $20 of usage credit, $0.00 of usage
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.
$20.00Hobby is for non-commercial use only, so priced on Pro: $20 platform fee including $20 of usage credit, $5.75 of usage

Resources the agent created

KindNamePlanList price / monthPricing
projectadb-9eaes-dataviz-web$0.00no fixed fee; usage within the plan's included allowance

The agent estimated $0.00 a month.

Code

Code
534 lines in 14 files (HTML 311, JavaScript 223, JSON 28, Markdown 9)
Dependencies
0 npm, 0 Python
Deploy config
vercel.json

The agent's sessions

PhaseStatusTimeTurnsTokensCostShell commands
Buildcompleted2m 30s17742.1K$0.6412
Deploycompleted1m 23s9544.9K$0.208

The agent's deploy summary

The dashboard is live at https://adb-9eaes-dataviz-web.vercel.app, and every requirement in TASK.md works through that URL.

What I deployed: one Vercel project, adb-9eaes-dataviz-web (prj_U5N4IOGrSBC1Mwibwv59Q3RI2pct), using the Vercel CLI and production deploys. The dashboard page is served as a static file, and /api/summary, /api/orders and /api/options run as Node functions. Those functions read the CSV, which is bundled with them and held in memory. There's no database or other resource, so the estimated cost is $0 a month.

Tests against the public URL:

  • Summary API: gives the same numbers as the local run. With no filters it returns 2,400 orders and $1,839,455.69. North from 2025-06-01 to 2025-07-15 returns 53 orders and $37,717.48.
  • Edge cases: a filter that matches nothing returns zeros and empty arrays, and a badly formatted date gets a 400.
  • Dashboard: in a headless browser on the live site, selecting Furniture changed the orders tile from 2,400 to 599 and the category chart to a single bar, without a page reload and with no page errors.
  • Private files: the raw CSV and .env files are not reachable over the web.

Notes:

  • Only the main address above is public. The per-deployment addresses Vercel also creates stay behind its default login protection; I left that setting alone.
  • Linking the project made the CLI write a .env.local file. I added it to .gitignore and .vercelignore and redeployed, so it isn't committed or deployed.
  • I didn't create any credentials, so there's no .env file. human_steps in deployment.json is empty because nothing needed a person.

Nothing failed.

8 shell commands during deploy
  1. 3s git status --short | head; ls -a; which vercel || npm i -g vercel@latest >/dev/null 2>&1; vercel --version
  2. 19s printf '.env\n' >> .gitignore && printf '.env\n.git\ntest\nnode_modules\n' > .vercelignore && vercel link --yes --project adb-9eaes-dataviz-web --scope "$VERCEL_TEAM_ID" --token "$VERCEL_TOKEN" 2>&1 |
  3. 33s cat .vercel/project.json; echo; grep -c . .env.local; vercel ls adb-9eaes-dataviz-web --scope "$VERCEL_TEAM_ID" --token "$VERCEL_TOKEN" 2>&1 | tail -5
  4. 39s printf '.env.local\n.env*\n' >> .vercelignore; curl -s -H "Authorization: Bearer $VERCEL_TOKEN" "https://api.vercel.com/v9/projects/adb-9eaes-dataviz-web?teamId=$VERCEL_TEAM_ID" | python3 -c "import j
  5. 43s vercel deploy --prod --yes --scope "$VERCEL_TEAM_ID" --token "$VERCEL_TOKEN" >/tmp/dep.log 2>&1; grep -o 'https://[^ ]*vercel.app' /tmp/dep.log | sort -u; for u in https://adb-9eaes-dataviz-web.vercel
  6. 56s U=https://adb-9eaes-dataviz-web.vercel.app; curl -s $U/ | grep -o '<title>.*</title>'; curl -s "$U/api/summary?region=North&start=2025-06-01&end=2025-07-15"; echo; curl -s "$U/api/summary?category=X";
  7. 1m 01s mkdir -p /tmp/shot && cd /tmp/shot && npm init -y >/dev/null && npm i playwright@1 >/dev/null 2>&1 && npx playwright install chromium >/dev/null 2>&1; cat > s.mjs <<'EOF'
  8. 1m 12s cat > deployment.json <<'EOF'

Raw data