PollXYZ
A city-scoped opinion polling app where the demographic result, not the user, is the product.
- agents in the pre-launch security audit
- 57
- raw findings to verified vulnerabilities
- 46 → 23
- critical access-control flaws, both closed
- 2
The problem
Online polls carry no verified context and no geographic signal, so bot votes and duplicate accounts make the results worthless as data. PollXYZ scopes each poll to a city, state, country or the world, keeps users pseudonymous with any real name encrypted on the device, and sells the demographic breakdown rather than the audience. The entire product rests on one guarantee — one device, one vote.
What I built
A monorepo with an Expo mobile app, a static marketing site, and shared packages for the AI layer, anti-bot checks, cryptography and data access. The backend is Supabase Postgres with row-level security and edge functions. Polls are generated, then approved by an admin before publication — users can never create them, which is what keeps the question set comparable across regions.
Optional real names are encrypted on-device under a key derived from a recovery phrase and held in the platform keychain, so the operator cannot read them. Voting supports a per-poll anonymous mode with guest votes counted in a separate bucket.
The majority of the recorded engineering, though, is remediation. A pre-launch security audit found the vote-integrity guarantee was enforced only in the client, and the work that followed was four batches of database patches, three edge functions rewritten, and a set of client changes — all driven by findings rather than by the roadmap.
The hard part
Auditing the product into a do-not-ship verdict
The audit was run as a fan-out of 57 agents: reconnaissance, then nine parallel finders each working a separate dimension, then an adversarial verification pass over every finding. It produced 46 raw findings, of which 43 survived verification and 3 were refuted as false positives, deduplicating to 23 distinct vulnerabilities — 2 critical, 12 high, 7 medium, 2 low. The verdict was do-not-ship.
The most valuable part was the verification pass, and the second-most valuable was what the findings had in common. Both criticals were the same mistake in different clothes: a privileged server-side path that trusted a caller-supplied identity without verifying it, in a context where the database's own row-level security had been deliberately bypassed. The one-device-one-vote guarantee failed the same way — enforced in the client, with a database constraint that a null value slipped straight past. Running an adversarial pass against your own work before launch, rather than treating the checklist as the safety net, is the practice I took from it.
Outcome
- A 57-agent audit reduced 46 raw findings to 23 verified vulnerabilities, with 3 refuted rather than accepted on face value.
- Both critical findings closed, along with four batches of database patches and three rewritten edge functions.
- Vote integrity moved out of the client into a server-side procedure that validates the option belongs to the poll, enforces one account per device, and rate-limits.
- Deferred items were recorded with reasons rather than quietly dropped.
Want something like this built? I take on a small number of projects at a time.