Security
Your voters' data, guarded.
Plain-language summary of how Groundgame handles campaign and voter data, rewritten from a completed security audit of the codebase. Every point below describes what the code does and what the tests prove — not aspirations.
Campaign isolation, re-proven per module
Every campaign's data is walled off from every other campaign's, and isolation is tested module by module — voter records, searches, notes, events, matching, alerts — by planting look-alike voters on both sides of the boundary and proving no read ever crosses it. The database enforces the same rule with row-level security.
A tested authorization matrix
Owner, staff, and volunteer roles check against a deny-by-default capability matrix on every sensitive action, server-side. Volunteers never see the voter file, exports, sends, money, or settings. The test suite enumerates every role against every capability on every run.
Rate limiting with stated reasons
Every product API route sits behind rate limiting with tighter budgets on imports, sends, signup, and the public contact endpoint — and every refusal names the budget it hit and why it exists. This site is static files and runs no endpoints at all.
Hardened uploads
CSV and Excel imports enforce size, row, and cell bounds. Formula-looking content is treated as inert text on the way in and escaped on the way out, so a spreadsheet app never executes it. Zip bombs are cancelled mid-decompression. Malformed files fail with a plain error, never a hang or a half-import.
Security headers everywhere
The product sends a content security policy, frame denial, nosniff, strict referrer policy, and HSTS on every route; this site serves the same header set from its CDN configuration, spelled out value-for-value in the deploy runbook.
Your campaign is isolated; the data foundation is shared
No other customer can sign in to your campaign, read your screens, or browse your records — the isolation suite proves it on every run. Contributed data and corrections do flow into the shared foundation every campaign draws from, under the licence the terms state in plain words (section 7) — we would rather you read that before signing up than discover it after.
Dates of birth never leave the server
The product shows a voter's age in whole years, computed server-side. The exact date of birth is never displayed, never exported, and the log boundary refuses it by test.
Benchmarks are aggregates with a floor
Anything RENDERED to you as a benchmark is computed over a minimum of five campaigns with your own campaign excluded; below the floor you see nothing rather than an approximation. Every cross-campaign read goes through one audited gateway — the chokepoint that keeps a broad licence accountable.
Exemptions and opt-outs are honored automatically
Public-records-exempt voters are excluded from every contact export; suppression lists and opt-outs are re-checked server-side on every send and every click-to-call.
Everything is audited
Imports, exports, bulk reads, sends, and single-voter record reads are written to an audit log with who, what, and how many — visible to your campaign in Settings.
No credentials in the code
An automated secrets scan runs inside the test suite on every build: source, docs, and configs are checked for key-shaped strings, and the environment inventory must hold placeholders only.
Deletion, honestly
Deleting a campaign removes access and the campaign, with a full export one click away first. It does not unwind the licence, contributed data, or derived work — the deletion screen says so before the button, in the same words as the terms. Where a statute grants you a deletion right no contract can waive, the statute wins: an operator executes it on its own audit trail and tells you plainly what was removed and what could not be.
Honest limits
The audit's open items are written down, not hidden: a framework upgrade is queued before launch to clear published advisories, and our content security policy still permits inline scripts while we move to nonces. The internal data-handling document states each limit next to the control it belongs to, and this page changes when the code does.
How we handle your data in full: see the privacy policy and terms of service.
Trust, then verify.
Ask us anything about data handling on a demo call; we'll walk you through the isolation, the role matrix, and the audit log.
Talk to us