Skip to content

✨ Load voting content from S3 with minimal voter status (main) - #3165

Open
edulix wants to merge 7 commits into
feat/meta-12767/main-backendfrom
feat/meta-12767/main-portal
Open

✨ Load voting content from S3 with minimal voter status (main)#3165
edulix wants to merge 7 commits into
feat/meta-12767/main-backendfrom
feat/meta-12767/main-portal

Conversation

@edulix

@edulix edulix commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Parent issue: https://github.com/sequentech/meta/issues/12767

Load election metadata and selected ballot styles from S3 using minimal GetVoterStatus. Isolate downloads by authenticated session, retain eligibility checks, and exercise full voting journeys through shared Chromium adapters.

Stack

  1. 📚 Voting load guides and synchronized code examples (main) #3163 — documentation and code tabs
  2. ✨ Private S3 ballot publications and scoped cast validation (main) #3164 — publications and cast backend
  3. ✨ Load voting content from S3 with minimal voter status (main) #3165 — voting portal and browser adapters
  4. ✨ Native Rust voting load preparation, workers and reports (main) #3149 — native Rust load tooling

Documentation

Copilot AI lite review requested due to automatic review settings September 8, 2026 09:22
@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 24 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 071b4132-b081-4b04-ab9a-04fa6db677d4

📥 Commits

Reviewing files that changed from the base of the PR and between b14b8db and eef7af6.

⛔ Files ignored due to path filters (1)
  • packages/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (67)
  • packages/admin-portal/graphql.schema.json
  • packages/admin-portal/src/gql/graphql.ts
  • packages/admin-portal/src/translations/cat.ts
  • packages/admin-portal/src/translations/en.ts
  • packages/admin-portal/src/translations/es.ts
  • packages/admin-portal/src/translations/eu.ts
  • packages/admin-portal/src/translations/fr.ts
  • packages/admin-portal/src/translations/gl.ts
  • packages/admin-portal/src/translations/nl.ts
  • packages/admin-portal/src/translations/tl.ts
  • packages/admin-portal/src/types/keycloak.ts
  • packages/ballot-verifier/graphql.schema.json
  • packages/ballot-verifier/src/gql/graphql.ts
  • packages/graphql.schema.json
  • packages/package.json
  • packages/results-portal/graphql.schema.json
  • packages/results-portal/src/gql/graphql.ts
  • packages/ui-core/package.json
  • packages/ui-essentials/package.json
  • packages/ui-essentials/src/components/CustomAutocompleteArrayInput/CustomAutocompleteArrayInput.tsx
  • packages/voting-portal/graphql.schema.json
  • packages/voting-portal/package.json
  • packages/voting-portal/playwright.capture.config.ts
  • packages/voting-portal/playwright.scale.config.ts
  • packages/voting-portal/src/__mocks__/uiCoreTestEntry.ts
  • packages/voting-portal/src/gql/gql.ts
  • packages/voting-portal/src/gql/graphql.ts
  • packages/voting-portal/src/hooks/useUpdateTranslation.ts
  • packages/voting-portal/src/hooks/useVoterContext.test.tsx
  • packages/voting-portal/src/hooks/useVoterContext.ts
  • packages/voting-portal/src/index.tsx
  • packages/voting-portal/src/providers/ApolloContextProvider.test.tsx
  • packages/voting-portal/src/providers/ApolloContextProvider.tsx
  • packages/voting-portal/src/providers/AuthContextProvider.tsx
  • packages/voting-portal/src/providers/SettingsContextProvider.tsx
  • packages/voting-portal/src/queries/GetElections.ts
  • packages/voting-portal/src/queries/GetVoterStatus.ts
  • packages/voting-portal/src/routes/BallotLocator.tsx
  • packages/voting-portal/src/routes/ConfirmationScreen.tsx
  • packages/voting-portal/src/routes/ElectionSelectionScreen.tsx
  • packages/voting-portal/src/routes/PublishedBallot.test.tsx
  • packages/voting-portal/src/routes/PublishedBallot.tsx
  • packages/voting-portal/src/services/ApolloErrors.test.ts
  • packages/voting-portal/src/services/ApolloErrors.ts
  • packages/voting-portal/src/services/PublishedBallots.test.ts
  • packages/voting-portal/src/services/PublishedBallots.ts
  • packages/voting-portal/src/store/castVotes/castVotesSlice.test.ts
  • packages/voting-portal/src/store/castVotes/castVotesSlice.ts
  • packages/voting-portal/src/store/electionEvents/electionEventsSlice.test.ts
  • packages/voting-portal/src/store/store.test.ts
  • packages/voting-portal/src/store/store.ts
  • packages/voting-portal/src/translations/cat.ts
  • packages/voting-portal/src/translations/es.ts
  • packages/voting-portal/src/translations/eu.ts
  • packages/voting-portal/src/translations/fr.ts
  • packages/voting-portal/src/translations/gl.ts
  • packages/voting-portal/src/translations/nl.ts
  • packages/voting-portal/src/translations/tl.ts
  • packages/voting-portal/src/utils/voterSessionScope.test.ts
  • packages/voting-portal/src/utils/voterSessionScope.ts
  • packages/voting-portal/test/load/ballotTypes.ts
  • packages/voting-portal/test/load/capture.spec.ts
  • packages/voting-portal/test/load/flow.ts
  • packages/voting-portal/test/load/scale.spec.ts
  • packages/voting-portal/test/load/status.spec.ts
  • packages/voting-portal/tsconfig.capture.json
  • packages/voting-portal/tsconfig.json

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are correctness and CI-blocking issues in the changed code (notably JWT base64url decoding in voterSessionScope and related TypeScript/lint problems) that should be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR shifts the voting portal’s bootstrap flow to fetch election/event metadata and selected ballot styles from published S3 snapshots referenced by a minimal GetVoterStatus query, while keeping voter-eligibility checks and isolating cached downloads/state by authenticated session. It also adds Playwright-based capture/scale runners to exercise full Chromium voting journeys.

Changes:

  • Add GetVoterStatus query + useVoterContext hook to load published election/event metadata and (optionally) a selected ballot style from S3, then seed Apollo cache/Redux state.
  • Add session-scoping utilities and a clearVoterSession store reset path tied to auth scope changes.
  • Add Playwright capture/scale/status harnesses and TypeScript typecheck scripts for the new e2e tooling.
File summaries
File Description
packages/yarn.lock Adds Playwright dependency resolution for new load/capture tooling.
packages/voting-portal/tsconfig.json Adds explicit Node/Jest types and formatting updates.
packages/voting-portal/tsconfig.capture.json New TS config for Playwright capture/scale scripts.
packages/voting-portal/test/load/status.spec.ts New Playwright test to measure authenticated GetVoterStatus performance.
packages/voting-portal/test/load/scale.spec.ts New Playwright shard runner for finite multi-voter Chromium journeys.
packages/voting-portal/test/load/flow.ts Shared Playwright helpers for login and casting flow.
packages/voting-portal/test/load/capture.spec.ts New diagnostic Playwright capture for a full login-to-cast journey (HAR + summaries).
packages/voting-portal/test/load/ballotTypes.ts New TS types for captured/prepared cast payloads and voter-status references.
packages/voting-portal/src/utils/voterSessionScope.ts New helper to derive a cache partition key from JWT claims.
packages/voting-portal/src/utils/voterSessionScope.test.ts Unit tests validating scope stability/invalidation behavior.
packages/voting-portal/src/translations/tl.ts Adds new localized strings for invalid login hint parameters.
packages/voting-portal/src/translations/nl.ts Adds new localized strings for invalid login hint parameters.
packages/voting-portal/src/translations/gl.ts Adds new localized strings for invalid login hint parameters.
packages/voting-portal/src/translations/fr.ts Adds new localized strings for invalid login hint parameters.
packages/voting-portal/src/translations/eu.ts Adds new localized strings for invalid login hint parameters.
packages/voting-portal/src/translations/es.ts Adds new localized strings for invalid login hint parameters.
packages/voting-portal/src/translations/cat.ts Adds new localized strings for invalid login hint parameters.
packages/voting-portal/src/store/store.ts Adds clearVoterSession action and root reducer reset on session changes.
packages/voting-portal/src/store/store.test.ts New test ensuring session-scope changes reset eligibility/participation state.
packages/voting-portal/src/store/electionEvents/electionEventsSlice.test.ts Updates test data to include delegated voting policy in presentation.
packages/voting-portal/src/store/castVotes/castVotesSlice.ts Adds parseCastVoteStatus to validate DB status strings.
packages/voting-portal/src/store/castVotes/castVotesSlice.test.ts Adds tests for cast status parsing behavior.
packages/voting-portal/src/services/PublishedBallots.ts New S3 publication JSON loader with client-scoped in-flight dedupe and validation.
packages/voting-portal/src/services/PublishedBallots.test.ts Tests worker concurrency and per-client in-flight download dedupe/eviction.
packages/voting-portal/src/services/ApolloErrors.ts New helper to classify Apollo 4 transport errors without ApolloError wrapper.
packages/voting-portal/src/services/ApolloErrors.test.ts Unit tests for the Apollo transport error classifier.
packages/voting-portal/src/routes/PublishedBallot.tsx New route wrapper to seed store from published snapshots and preserve choices on refresh.
packages/voting-portal/src/routes/PublishedBallot.test.tsx Test to ensure published-style reload preserves voter choices.
packages/voting-portal/src/routes/ElectionSelectionScreen.tsx Switches bootstrap to useVoterContext, adjusts revote/materials logic and polling.
packages/voting-portal/src/routes/ConfirmationScreen.tsx Improves mutation typing and guards print action when tracker URL is missing; adds testids.
packages/voting-portal/src/routes/BallotLocator.tsx Removes ballot-style bootstrap query side effects.
packages/voting-portal/src/queries/GetVoterStatus.ts New minimal query returning publication URL refs + cast metadata.
packages/voting-portal/src/queries/GetElections.ts Removes eml field from elections query selection.
packages/voting-portal/src/providers/SettingsContextProvider.tsx Widens children type to React.ReactNode.
packages/voting-portal/src/providers/AuthContextProvider.tsx Widens children type to React.ReactNode.
packages/voting-portal/src/providers/ApolloContextProvider.tsx Adds session scoping + store reset on scope changes; stops Apollo client on cleanup.
packages/voting-portal/src/providers/ApolloContextProvider.test.tsx Tests refresh vs scope-change vs logout behavior for session state clearing.
packages/voting-portal/src/index.tsx Adds PublishedBallot route wrapper under election route.
packages/voting-portal/src/hooks/useVoterContext.ts New hook to load minimal status, download publication snapshots, and seed Apollo cache.
packages/voting-portal/src/hooks/useVoterContext.test.tsx Tests schema validity, request minimization, scoping, retries, and download safety.
packages/voting-portal/src/hooks/useUpdateTranslation.ts Adapts translation overwrite call to handle optional presentation.
packages/voting-portal/src/gql/graphql.ts Regenerates GraphQL types (adds new fields/ops including get_ballot_files_urls).
packages/voting-portal/src/gql/gql.ts Regenerates typed-document mapping including new GetVoterStatus.
packages/voting-portal/src/mocks/uiCoreTestEntry.ts Extends ui-core re-exports for tests (ElectionEventPresentation + candidatePresentation).
packages/voting-portal/playwright.scale.config.ts New Playwright config for scale shard runs.
packages/voting-portal/playwright.capture.config.ts New Playwright config for capture/status runs.
packages/voting-portal/package.json Adds Playwright dev dependency and typecheck scripts.
packages/voting-portal/graphql.schema.json Updates introspection schema (includes get_ballot_files_urls and other additions).
packages/ui-essentials/src/components/CustomAutocompleteArrayInput/CustomAutocompleteArrayInput.tsx Exports props interface for external typing.
packages/ui-essentials/package.json Adds build:types script for emitting declaration files.
packages/ui-core/package.json Adds build:types script for emitting declaration files.
packages/results-portal/src/gql/graphql.ts Regenerates GraphQL types (schema additions).
packages/results-portal/graphql.schema.json Updates introspection schema.
packages/package.json Formats nohoist list and adds voting-portal typecheck pipeline script.
packages/graphql.schema.json Updates shared introspection schema.
packages/ballot-verifier/src/gql/graphql.ts Regenerates GraphQL types (schema additions).
packages/ballot-verifier/graphql.schema.json Updates introspection schema.
packages/admin-portal/src/types/keycloak.ts Adds TENANT_DELETE permission enum entry.
packages/admin-portal/src/translations/tl.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/translations/nl.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/translations/gl.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/translations/fr.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/translations/eu.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/translations/es.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/translations/en.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/translations/cat.ts Adds translation for tenant-delete permission label.
packages/admin-portal/src/gql/graphql.ts Regenerates GraphQL types (schema additions).
packages/admin-portal/graphql.schema.json Updates introspection schema.
Review details
  • Files reviewed: 67/68 changed files
  • Comments generated: 5
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/voting-portal/src/routes/BallotLocator.tsx
Comment on lines 758 to 761
const hasBallotId = !!ballotId
const {data: dataBallotStyles} = useQuery<GetBallotStylesQuery>(GET_BALLOT_STYLES)
const {data: dataElections, loading: loadingElections} = useQuery<GetElectionsQuery>(
GET_ELECTIONS,
{
Comment on lines +8 to +9
const payload = token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/")
const claims = JSON.parse(atob(payload))
Comment on lines +21 to +23
default:
throw new Error("Unknown cast vote status")
}
Comment on lines +10 to +12
const initial = store.getState()
store.dispatch(setElection({id: "election", presentation: {}} as any))
store.dispatch(
Copilot AI review requested due to automatic review settings September 8, 2026 09:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

There are confirmed correctness/robustness issues in newly added session-scoping and status parsing that should be addressed before merge.

Review details

Suppressed comments (3)

packages/voting-portal/src/utils/voterSessionScope.ts:20

  • JWT payloads are base64url-encoded and commonly omit padding; calling atob() on an unpadded payload can throw in some environments. In that failure mode this function falls back to returning the whole token, which changes on routine refresh (exp) and will unnecessarily clear the voter session cache partition.
    packages/voting-portal/src/store/castVotes/castVotesSlice.ts:23
  • The thrown error omits the unexpected status value, which makes production debugging harder when the backend adds/changes statuses. Include the received value in the message.
    packages/voting-portal/src/routes/ElectionSelectionScreen.tsx:321
  • This effect no longer references ballotStyle, but it still appears in the dependency list; meanwhile election is referenced in the condition but not listed. Updating the dependency array avoids unnecessary re-runs and keeps dependencies aligned with the values used inside the effect.
  • Files reviewed: 67/68 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 8, 2026 10:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A confirmed JWT base64url decoding issue can cause session scoping to fall back to the raw token (leading to unnecessary scope churn and state clears), and a test leaks a mocked global.fetch across files.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

packages/voting-portal/src/utils/voterSessionScope.ts:9

  • JWT payloads are base64url-encoded and are often unpadded; calling atob() on an unpadded payload can throw and make this function fall back to returning the full token. That can cause the session scope to change on routine token refreshes (clearing cached state unexpectedly) and also keeps the raw token string as the cache key.
  • Files reviewed: 67/68 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +4 to +6
import {ApolloClient, InMemoryCache, ApolloLink} from "@apollo/client"
import {fetchPublicationJson, mapPublicationFiles, VoterFile} from "./PublishedBallots"

Copilot AI review requested due to automatic review settings September 8, 2026 10:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces a new authentication-scoped bootstrap path (GraphQL + S3 publication hydration) that affects core voting flows and caching/state boundaries, warranting final human verification despite unit test coverage.

Review details

Suppressed comments (1)

packages/voting-portal/src/store/castVotes/castVotesSlice.ts:23

  • parseCastVoteStatus throws a generic error that omits the unexpected status value, which makes production debugging harder when a new/invalid status reaches the client.
  • Files reviewed: 67/68 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Findeton pushed a commit that referenced this pull request Sep 8, 2026
Parent issue: sequentech/meta#12767

One complete k6/Chromium guide covers setup, workload sizing,
local/Docker/Kubernetes workers, reports and troubleshooting. Includes
synchronized engine examples, CLI reference, a real report screenshot
and a separate telephone guide.

Validation: Docusaurus build, Markdown-transform tests and Chromium
checks for synchronized tabs, persistence, keyboard navigation, mobile
layout and report images.

### Stack

1. #3163 — documentation and code tabs
2. #3164 — publications and cast backend
3. #3165 — voting portal and browser adapters
4. #3149 — native Rust load tooling

### Documentation

- **Voting load-testing guide** —
[Docusaurus](https://docs.sequentech.io/docusaurus/pr-preview/pr-3163/docs/developers/voting-portal/voter-status-performance)
·
[GitHub](https://github.com/sequentech/step/blob/feat/meta-12767/main/docs/docusaurus/docs/07-developers/05-voting-portal/voter-status-performance.md)
- **CLI setup** —
[Docusaurus](https://docs.sequentech.io/docusaurus/pr-preview/pr-3163/docs/developers/cli/cli)
·
[GitHub](https://github.com/sequentech/step/blob/feat/meta-12767/main/docs/docusaurus/docs/07-developers/02-cli/01-cli_cli.md)
- **Load CLI reference** —
[Docusaurus](https://docs.sequentech.io/docusaurus/pr-preview/pr-3163/docs/developers/cli/voting-load-reference)
·
[GitHub](https://github.com/sequentech/step/blob/feat/meta-12767/main/docs/docusaurus/docs/07-developers/02-cli/voting-load-reference.md)
- **Telephone load-testing guide** —
[Docusaurus](https://docs.sequentech.io/docusaurus/pr-preview/pr-3163/docs/developers/ivr/telephone-load-testing-guide)
·
[GitHub](https://github.com/sequentech/step/blob/feat/meta-12767/main/docs/docusaurus/docs/07-developers/12-ivr/telephone-load-testing-guide.md)

---------

Co-authored-by: Eduardo Robles <edulix@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants