Protocol Edition · Read Locally, Verify Anywhere No. IPP‑00
InterPoll
A poll no single server can rewrite.
How it actually works

The machinery under a vote you can't take back.

This page explains InterPoll twice on every topic: in plain language for anyone who just wants to understand what they're trusting, and — one tap away, marked ▸ for the technically curious — the actual mechanism underneath.

Most polls live on one company's server. That company can quietly change a result, delete an inconvenient vote, or shut the whole thing down — and you'd have no way to know.
InterPoll spreads the record across every participating device instead, and locks each vote with a signature only your device can produce. A relay can slow the mail down, or refuse to carry it. It cannot forge your signature, and it cannot rewrite what's already been sealed.
Three layers

One vote, three separate machines

Nothing about InterPoll runs in one place. A vote touches a private ledger on your device, a shared content graph copied across every peer, and a real-time sync layer that lets everyone see it happen — each with a different job, and a different reason you can trust it.

Layer 1

The Local Chain

Every vote you cast becomes a permanent entry in a private ledger that lives on your own device. Each entry is stamped with a fingerprint of the one before it, so nobody — including you — can quietly edit history without it showing.

For the technically curious
ChainService creates one block per action (vote, post, etc.), computes its SHA-256 hash over the payload plus the previous block's hash, and signs it with the device's local keypair from KeyVaultService. Blocks persist in IndexedDB via storageService. Because each hash embeds the prior one, any retroactive edit breaks the chain — detectable by anyone who replays it, including relays, which never hold the signing key.
Layer 2

The Content Graph

Polls, posts, comments and profiles aren't stored in one database — they're copied across every device and relay connected to the network. As long as one honest copy exists anywhere, the content survives.

For the technically curious
GunService wraps a GunDB graph replicated peer-to-peer. Polls, posts, comments, communities and profiles read/write through the v3 namespace (see NAMESPACED_ROOTS in gunService.ts). Gun's CRDT-style merge resolves conflicting writes deterministically without a central authority. Private communities layer AES-256-GCM (EncryptionService) on top, with keys held only in KeyVaultService — lose the key, lose the data, by design.
Layer 3

Peer Sync

Your browser tabs and other people's devices stay in sync in real time over a lightweight relay. If the relay is slow, censoring, or offline, it can delay you seeing new activity — it can never fake a vote nobody signed.

For the technically curious
WebSocketService discovers peers and rebroadcasts new signed blocks with automatic relay failover; BroadcastService mirrors chain state across same-origin browser tabs via the BroadcastChannel API. A two-phase commit (/api/vote-authorize → /api/vote-confirm) issues a short-lived reservation token before the vote lands in the relay's registry, closing the double-submit race without granting the relay any forgery power.
Beyond the ballot

Posts and comments carry the same guarantees

InterPoll isn't only polls. Posts, threaded comments, and the communities they live in all move through the same three layers — nothing about publishing an article or replying to one gets a lighter version of the trust model.

Publishing

A post is signed like a vote

When you publish a post, your device signs it the same way it signs a vote — the difference is what's inside the block, not how it's protected. Nobody can put words in your mouth after the fact.

For the technically curious
PostService builds the post payload and hands it to the same ChainService signing path used for votes, then writes it into the GunDB content graph via GunService for replication. Edits after publication are new signed entries, not silent mutations of the original — the original stays intact in the chain.
Discussion

Comments are threaded, not siloed

Replies attach to a post or poll and nest under one another, so a discussion keeps its shape instead of collapsing into a flat, easily-buried list.

For the technically curious
CommentService stores each comment as a node referencing its parent (post, poll, or another comment) inside the same Gun namespace, so a full thread reconstructs from the graph without a central "comments table." Each comment is independently signed and replicated like any other content object.
Display

Real name, or a consistent pseudonym

You choose whether posts and comments show your real name. If you opt out, InterPoll doesn't just say "Anonymous" — it gives you the same pseudonym every time on that thread, so people can still follow a conversation.

For the technically curious
Display name resolves from the profile's showRealName flag; when false, generatePseudonym(postId, authorId) deterministically derives a stable alias scoped to that post, so the same author reads consistently across a thread without exposing their identity.
Propagation

No two-phase check-in, just word of mouth

A post doesn't go through the vote-authorize/vote-confirm handshake — there's no registry slot to reserve. Instead it spreads the way an announcement spreads through a crowd: your device tells its peers, and each of them tells theirs.

For the technically curious
After PostService commits the signed block to the local chain, GunService writes it into the Gun graph, which replicates it to every connected relay and peer via Gun's own sync protocol — no vote-registry involvement at all. WebSocketService additionally pushes a lightweight notification over the relay so already-open clients pick up the new post without polling, and BroadcastService mirrors it into other tabs on the same origin. If a relay is offline, Gun's replication resumes the moment any other peer holding a copy reconnects — propagation delay, not data loss.
Step by step

What happens between your click and your receipt

Nine steps run in the time it takes to see a confirmation screen. Step through them — the row of blocks below tracks the chain forming as each one lands.

For the technically curious
Guarding the ballot box

Five layers standing between the network and a fake vote

No single mechanism carries all the weight — each one closes a different way a vote could be gamed.

Device fingerprinting

Your browser's own characteristics produce a consistent identifier, so the same device can't quietly rack up extra votes. SHA-256 over stable browser properties (VoteTrackerService).

Two-phase vote authorization

A vote is reserved, then confirmed — a duplicate submission in the gap between the two is rejected. /api/vote-authorize → /api/vote-confirm, HMAC-signed tokens.

Single-use invite codes

Private polls can require a code that's consumed the instant it's used — nobody can hand it to two people. Atomic consumption in GunDB via InviteLinkService.

Optional identity gating

Poll owners can require a Google or Microsoft sign-in before a vote counts, trading anonymity for stronger one-person-one-vote guarantees. OAuth handled by AuditService; relay-side callback verification.

Rate limiting & bot scoring

The relay watches submission patterns and throttles anything that looks automated, independent of what any single vote claims about itself.

Cryptographic signatures

Underneath all four: every block is signed by a key that never leaves your device, so nothing above matters more than this — a relay can enforce policy, but it can never sign in your name.

The honest threat model

What the relay can — and can't — do to your vote

InterPoll doesn't pretend the relay is powerless. It's just narrowly powerless, in a specific and important way.

A relay can

  • Delay how quickly your vote reaches other peers
  • Refuse to relay a poll at all — go dark, get replaced
  • See who is submitting, unless you're on a private community
  • Rate-limit or gate registration behind OAuth, if the poll owner asked for it

A relay cannot

  • Forge a vote — it never holds anyone's signing key
  • Rewrite a sealed block without breaking the hash chain, visibly
  • Delete your local copy of your own chain history
  • Erase content that's already replicated to other honest peers