civicos-relay¶
Coordination relay for voice casting, subscriptions, and relay-to-relay sync.
Location: packages/civicos-relay/
Services¶
VoiceService¶
Public expression of civic interest on entities (agenda items, decisions, initiatives).
cast_voice(voice)— Submit a signed stance (support/oppose/watching)get_counts(entity)— Aggregate voice counts per entityverify(voice)— Verify signature
One key = one stance per entity. Casting a new stance revokes the previous one.
ActionService¶
Track commitments and completions on civic actions.
record_commitment(action)— Record an action commitmentrecord_completion(action)— Record completionget_counts(entity)— Action counts
RelayService¶
Event routing and subscription management.
subscribe(subscription)— Subscribe to events by topic, geography, or event typeunsubscribe(id)— Remove subscriptionemit(event)— Route event to subscribers
ProvenanceService¶
Trust signals for voice quality — tracks which keys have touched which entities and jurisdictions.
SyncService¶
Voice and event synchronization between peer relays. Pull-based: each relay periodically fetches new voices from configured peers via GET /coordination/sync/voices.
sync_from_peer(peer)— Pull voices from a peer, verify signatures, importexport_voices(request)— Serve voices for peer consumption- Health checking with auto-disable of unhealthy peers
Configure peers via RELAY_PEERS (comma-separated URLs) and interval via RELAY_SYNC_INTERVAL (seconds, default 300).
AttestationService¶
Orchestrates multi-issuer code redemption and attestation issuance.
register_issuer(registration)— Register an issuer organizationaccept_code_batch(signed_event)— Accept issuer-signed code batchesredeem_code(code, pubkey, sig, created_at)— Redeem code via issuer's signer
Storage¶
PostgresStorage— Production. UsesRELAY_DATABASE_URL(separate from the civic data database).- Tables:
coordination_voices,coordination_subscriptions,coordination_initiatives,coordination_attestation_codes,coordination_attestations,coordination_issuer_registry,coordination_sync_cursors, and more InMemoryStorage— Fallback for local dev/testing.
Selection: RELAY_DATABASE_URL > DATABASE_URL > in-memory.
Attestation¶
The relay verifies attestation proofs (kind-30850 events) embedded on voices and comments. Trusted organizations run civicos-signer instances with their own keys, and the relay calls out to their /sign endpoints during code redemption. The relay maintains a registry of trusted issuer pubkeys per jurisdiction in coordination_issuer_registry.
Cryptography¶
All voices are signed with secp256k1 Schnorr signatures (Nostr-compatible, BIP-340). Not P-256 ECDSA.
Deployment¶
# Production (Modal)
modal deploy packages/civicos-relay/src/civicos_relay/modal_relay.py
# Multi-platform (Modal, Fly.io, or Docker)
./scripts/deploy-relay.sh <jurisdiction> <platform>
Each relay instance is self-contained — a single jurisdiction can be served by one relay, or multiple relays can peer via RELAY_PEERS for federation.