Skip to content

Security

Precise about what we protect, and how.

This page describes the controls as they are built. It avoids words like certified or end-to-end because we have not earned them yet. If something here is unclear, ask info@yost.group.

How voter access works

Voters do not have accounts or passwords. A member opens the election link, enters the email on the approved roster, and receives a one-time code or a sign-in link.

  • Codes and links are generated from cryptographically random values. Only a hash is stored; the plaintext exists in the email and nowhere else.
  • Codes expire after 10 minutes and links after 15 minutes. Requesting a new one invalidates any unused earlier credential.
  • A code allows 5 attempts, then the challenge is void and a new code must be requested.
  • Requests are throttled per email address and per source, with backoff and a support path, to resist roster enumeration. The response never reveals whether an address is on the roster.
  • Opening a sign-in link does not vote or create a session. A confirmation action is required so email scanners cannot consume it. Credentials are stripped from the address after exchange and never logged.
  • A voter session lasts 60 minutes. Re-authenticating never resets participation or grants a second ballot.

Ballot secrecy

Identifiable roster and participation records are kept apart from vote choices.

  • A ballot row stores the selections and the date bucket. It carries no member id, email address, IP address, access token, or participation key. Exact submission times are deliberately not stored.
  • Identity and ballot writes happen in one transaction, without retaining a member-to-ballot join key. Exactly one accepted ballot per eligible member is enforced with a database constraint and an idempotency key, so retries and concurrent tabs cannot create a second ballot.
  • The receipt is a random confirmation code. It proves this system accepted a ballot; it does not contain choices, and it is not sent by email with them.
  • Support staff can confirm that a member participated and resend access. They cannot view or enter selections for anyone.
  • Ordinary exports never include row-level ballots or exact timestamps.

This provides confidentiality from administrators and from exports. It is not a claim of anonymity against a privileged infrastructure operator with raw database access, nor a cryptographic end-to-end verifiable scheme.

Integrity of the result

  • Eligibility is derived from the approved roster and cutoff, then frozen at scheduling together with a hash of the election configuration and a snapshot of the brand voters will see.
  • Opening, slate close, roster exceptions, deadline changes, cancellation, certification, and publication each require a reason and approval by a second authorized person. One account cannot satisfy both roles for the same action.
  • The audit trail is append-only and records actor, approver, action, time, and configuration version. Election managers cannot modify it. It exports separately from roster and results and never contains credentials or ballot choices.
  • Opening is inclusive and closing is exclusive, checked against server time at the moment of acceptance. A stale page or an expired countdown cannot bypass the closing boundary. Closed elections cannot reopen.
  • After close, the participation count is reconciled against the ballot count and every total is recomputed. Certification is blocked on any mismatch.
  • Ties are never resolved automatically. A tie that affects a seat is reported as unresolved and requires an approved adjudication or a separate runoff. A sole candidate still requires the configured vote.
  • Corrections after certification create a new certified version with a visible correction record. Prior versions are preserved.

Administrator security

  • Administrators sign in with a password stored as a salted scrypt hash and enroll authenticator-app multi-factor authentication (TOTP). The platform can require an MFA-passed session for all administrative access.
  • Roles are separate and scoped to one association: owner, election manager, brand editor, certifier, and auditor. No role can see a member's vote choices. A certifier must be a different account from the manager who acted.
  • Sessions use secure, HttpOnly cookies with a fixed lifetime of twelve hours and are revoked on sign-out.
  • Every query, background job, export, and themed page is scoped to the association. An identifier from another association returns nothing.

Platform

  • All traffic is served over TLS. Responses carry a restrictive Content Security Policy that permits no third-party scripts, along with frame-ancestors none, nosniff, a no-referrer policy, and a locked-down Permissions-Policy. The site loads no third-party fonts or analytics.
  • The application and its managed PostgreSQL database run on Railway, with encryption at rest and backups managed by the platform.
  • Email is sent through Resend from a dedicated sending domain with SPF and DKIM published and a DMARC policy in place. Associations may send from their own domain after DNS verification.
  • Uploaded logos are validated for format, dimensions, and size. CSV exports are escaped so spreadsheet formulas cannot execute.

Your data

  • Your association owns its roster, elections, results, and audit trail. We process them only to run the service.
  • Export at any time: roster CSV, audit CSV, results CSV, the printable certification report, and a complete offboarding export of everything your association owns.
  • Retention is set per association and approved by the owner, and the approval itself is recorded in the audit trail. The default keeps election records for 24 months after certification.
  • On offboarding we provide the full export, then delete the association's data from the live system within 30 days. Backups are retained for no more than 90 days after that.
  • If we confirm a security incident affecting an association's data, we notify its account owner without unreasonable delay and no later than 72 hours after confirming it.
  • See the privacy policy for what is collected and why.

Responsible disclosure

If you believe you have found a vulnerability, write to info@yost.group with enough detail to reproduce it. We will acknowledge within two business days, keep you informed, and credit you if you wish. Please do not test against live elections, access data that is not yours, or run automated scanners against production without asking first.

Questions a board will ask, answered before they ask.

Start a trial, run a committee vote, and read the audit file it produces.