Skip to content

API returns raw vote counts in results endpoint — add confidence intervals and audit note #38

Description

@Just-Bamford

Summary

The results endpoint GET /api/ballots/:id/results returns raw vote
counts as a simple object — { "option-a": 45, "option-b": 32 }. For
observers and auditors to verify that results are reliable, they need
context about the data quality: how many votes are encrypted vs
decrypted, what was the total vote count, and is the tally consistent
with the Stellar blockchain. Without this metadata, a result page that
shows raw counts is not verifiable — observers have no way to know if
the tally is complete or if there were data errors.

Background

In backend/src/services/resultEngine.ts, the tally is computed and
returned as a simple count object. The GET /api/ballots/:id/results
endpoint returns only the counts. There is no audit trail, consistency
proof, or confidence interval included.

Scope

Backend

  • Update the results response to include metadata:
    {
      results: { "option-a": 45, "option-b": 32 },
      metadata: {
        total_votes: 77,
        ballotId: "...",
        ballot_title: "...",
        tally_timestamp: "2026-07-15T10:30:00Z",
        stellar_transaction_id: "...",
        is_consistent: true,
        encryption_note: "All votes encrypted with ballot-specific key"
      }
    }
    
  • Add tally_timestamp to the ballotResults table if not present
  • Include the Stellar transaction ID from the result publication step
  • Add an is_consistent flag showing the result of the contract
    consistency check (see contracts issue SOROBAN_CONTRACT_ID is empty — Stellar integration is silently inactive #12)
  • Add an audit note explaining the encryption and verification model

Frontend

  • Display the metadata alongside the results on the public results page
  • Show a badge or indicator for is_consistent: true/false
  • Display encryption_note in a collapsible section for power users
  • Show the Stellar link with the transaction ID for independent verification

Tests

  • Verify results response includes all metadata fields
  • Verify metadata is accurate (total_votes matches sum of counts)
  • Verify is_consistent flag matches contract state
  • Verify Stellar transaction ID is included

Relevant Files

  • backend/src/services/resultEngine.ts
  • backend/src/routes/results.ts
  • backend/prisma/schema.prisma (add tally_timestamp if needed)
  • frontend/src/pages/Results.tsx
  • backend/src/tests/results.test.ts

Acceptance Criteria

  • Results response includes metadata object
  • total_votes calculated correctly
  • tally_timestamp recorded and included
  • Stellar transaction ID included
  • is_consistent flag reflects contract verification
  • encryption_note explains the privacy model
  • Frontend displays metadata and transaction link
  • All tests pass
  • No TypeScript warnings

Out of Scope

  • Confidence intervals or statistical measures — metadata only
  • Historical results tracking — single result per ballot

Note for Contributors

The metadata makes results trustworthy. Observers can now independently
verify that the tally is complete (total_votes count), that it passed
on-chain consistency checks, and can look up the Stellar transaction
if they want to audit the blockchain record. This is the difference
between a result and a verifiable result.

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26backendBackend-related issuesenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions