Files
427e7578-d7bf-49c8-aee9-2dd…/specs/012-lightweight-server
2026-03-16 23:03:27 +13:00
..
2026-03-16 23:03:27 +13:00

status, created, tags, priority, created_at, depends_on, updated_at, completed_at, completed, transitions
status created tags priority created_at depends_on updated_at completed_at completed transitions
complete 2026-03-16
server
infra
high 2026-03-16T07:57:36.544Z
001-project-setup
2026-03-16T10:01:29.167Z 2026-03-16T10:01:29.167Z 2026-03-16
status at
complete 2026-03-16T10:01:29.167Z

Poll Snapshot Server

Status: Complete · Priority: High · Created: 2026-03-16 · Tags: server, infra

Overview

A minimal server that stores poll snapshots for public/offline viewing. This is the only server-side component — intentionally thin. No user accounts, no directory, no auth beyond signature verification.

Design

Tech Stack

  • Runtime: Cloudflare Workers (or a simple Bun server if self-hosting)
  • Storage: Cloudflare KV (or SQLite for self-hosted)
  • Auth: Snapshot writes are signed with the poll owner's Ed25519 private key

API Endpoints

  • PUT /api/polls/:id/snapshot — Store/update snapshot (signed by poll owner)
    • Body: { pollId, ownerId, ownerPeerId, title, description, options[], voteCounts, status, signature }
  • GET /api/polls/:id/snapshot — Fetch snapshot (public, no auth)

Security

  • Write operations require a valid Ed25519 signature
  • Verify signature against ownerId in the request body; bind pollId → ownerId on first write; reject future writes if ownerId changes
  • No sessions, no cookies, no passwords
  • Rate limiting on writes to prevent abuse

Data Model

// KV key: poll:{pollId}:snapshot → PollSnapshot

interface PollSnapshot {
  pollId: string;
  ownerId: string;
  ownerPeerId: string;
  title: string;
  description: string;
  options: { id: string; text: string }[];
  voteCounts: Record<string, number>;
  status: 'draft' | 'open' | 'closed';
  updatedAt: number;
}

Plan

  • Set up Cloudflare Workers project (or simple Bun server)
  • Implement Ed25519 signature verification middleware
  • Implement poll snapshot store/fetch endpoints
  • Add rate limiting
  • Deploy

Test

  • Snapshot store with valid signature succeeds
  • Snapshot store with invalid signature is rejected
  • Snapshot fetch returns stored data (public, no auth)
  • Second write from different ownerId is rejected
  • Rate limiting works

Notes

  • The P2P app works without this server — it just loses public sharing and offline snapshot viewing
  • Future: user directory endpoints can be added here when peer discovery is implemented (see archived spec 007)
  • Consider a TTL on snapshots (e.g., auto-expire 90 days after last update)