This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Sequent Voting Platform — an end-to-end verifiable, secure online voting system. The packages/ directory is both a Cargo workspace and a Yarn workspace, sharing Rust code with the frontend via WebAssembly compilation.
cargo build # Build all Rust packages
cargo build -p <package> # Build one package (e.g. braid, strand, windmill, sequent-core)
cargo build --release # Production buildyarn # Install all JS dependencies
yarn build:ui-core # Build ui-core library
yarn build:ui-essentials # Build ui-essentials library (must rebuild after changes)
yarn build:voting-portal # Build voting portal
yarn build:admin-portal # Build admin portal
yarn start:voting-portal # Dev server on port 3000
yarn start:admin-portal # Dev server on port 3002
yarn storybook:ui-essentials # Storybook on port 6006mvn clean package # Build all Keycloak extensions
mvn clean verify # Build and testcargo test # All tests
cargo test -p <package> # Single package tests
cargo test <test_name> # Single test by name
cargo test --release -p braid # Braid tests require --releaseyarn --cwd ./ui-essentials test # Jest tests for ui-essentials
yarn generate:voting-portal # Regenerate GraphQL types after schema changes
yarn generate:admin-portal # Same for admin portalcargo fmt -- --check # Check formatting
cargo fmt # Fix formatting
cargo clippy # Lintyarn lint # ESLint all frontend packages
yarn lint:fix # Auto-fix
yarn prettify # Check Prettier
yarn prettify:fix # Fix Prettierreuse lint # Every file must have SPDX headers- braid — Verifiable re-encryption mixnet (cryptographic shuffle). Features:
native,wasm,jemalloc - strand — Cryptographic primitives (Curve25519/Ristretto, Ed25519, SHA2/SHA3). Features:
rayon,wasm,fips_core - sequent-core — Shared core: ballot structures, crypto ops, PDF reports, Keycloak integration. Compiles to WASM for frontend. Features:
wasm,reports,keycloak,s3,sqlite - windmill — Celery-based task execution engine (RabbitMQ, GraphQL client, WASM plugin mgmt)
- harvest — Election management REST API (Rocket framework)
- immu-board — Tamper-evident bulletin board
- velvet — PDF/report generation CLI
- step-cli — CLI for election administration
- e2e — End-to-end testing framework
- voting-portal — Voter interface (React 19, Apollo Client, MUI 7, Keycloak auth, uses sequent-core WASM)
- admin-portal — Admin interface (React Admin, MUI data grid, TinyMCE, uses sequent-core + braid WASM)
- ballot-verifier — Standalone ballot verification tool
- ui-essentials — Shared UI component library (MUI, Storybook). Used by all portals
- ui-core — Lower-level shared utilities (HTML sanitization, i18n)
- Hasura — GraphQL API layer over PostgreSQL
- Keycloak — Identity management (one realm per tenant + one per election event)
- RabbitMQ — Task queue for Celery workers
- ImmuDB — Tamper-evident audit logging
- MinIO — S3-compatible object storage
- Rust crypto code compiles to WASM for browser use via
wasm-pack - Extensive Cargo feature flags for conditional compilation — always check
[features]in Cargo.toml - Celery + RabbitMQ for async task execution
- GraphQL codegen: queries live in
src/queries/, types generated withyarn generate:* - After editing ui-essentials components:
yarn prettify:fix:ui-essentials && yarn build:ui-essentials - sequent-core WASM rebuild: when changing
sequent-core, the WASM package often needs rebuilding for frontend changes to take effect
- REUSE license headers required on every file:
// SPDX-FileCopyrightText: 2025 Sequent Tech Inc <legal@sequentech.io> // SPDX-License-Identifier: AGPL-3.0-only - Vendored Cargo dependencies:
packages/vendor/— Cargo.toml uses[source.vendored-sources] - Pinned crate:
wasm-bindgen0.2.104 — do not change - Forked crate:
celeryuses a custom fork (Findeton/rusty-celery) - Hasura changes must go through
hasura console(not the web UI directly) for migrations to be tracked - Rust toolchain: 1.90.0 stable, WASM targets:
wasm32-unknown-unknown - Node.js: 20.x, package manager: Yarn (workspaces)
- Java: JDK 17 for Keycloak extensions
This is critical and applies to all code changes.
- Never build client-specific features — features are designed to serve all clients, not just the one requesting them. When a client needs something, design a general solution that accommodates that client AND all existing ones
- Features must be composable — clients should be free to select any combination of features. If certain combinations are incompatible, handle it at the design level: clearly communicate constraints to the client (e.g., via validation, warnings, or documentation), never silently break
- Policies use enums, not booleans — when modeling policies or configuration options, always use enums (in both Rust and TypeScript). Booleans don't scale — a policy that starts as on/off almost always grows into multiple modes
These are enforced during code review. Follow them to avoid revision requests.
- Handle
Option/Resultproperly — don't unwrap carelessly; return errors or use?operator. HandleNonecases explicitly rather than assuming values exist - Reuse types from
sequent-core::types— never duplicate types that already exist in sequent-core (e.g., usesequent_core::types::ceremonies::CountingAlgTypeinstead of creating localconst &strequivalents) - Use constants, not magic strings — extract repeated string literals into named constants (e.g.,
const APP_VERSION_DEV: &str = "dev") - Use Rust enums — prefer enums with
Display/FromStrover string constants when representing fixed sets of values
- No
anytypes — always use proper types. If the type is known, use it; if not, define one - Async error handling — always
awaitasync calls and wrap them intry/catchwhere errors can occur - Environment variables — prefix with the service name (e.g.,
B4_for B4,HASURA_for Hasura). When adding new env vars, also add them to the relevantdocker-composefiles
- No AI artifacts — remove any AI-generated comments, explanatory notes, or boilerplate that wouldn't be written by a human developer. Reviewers actively flag these. However, do NOT remove existing useful comments written by developers — only remove clearly AI-generated or stale ones
- No dead code or leftover comments — remove commented-out code, unused imports, and stale comments before submitting. Preserve existing comments that explain non-obvious logic
- No unresolved TODOs — address or remove TODO comments before merge. If work is deferred, create a ticket and reference it
- Backwards compatibility — when changing data structures or configs, consider how this affects existing data. Make new fields optional or provide defaults to avoid breaking older election events on import
- Branch naming:
feat/meta-<ticket>-<description>/mainorfix/meta-<ticket>/release/X.Y - PR body: must include
Parent issue: https://github.com/sequentech/meta/issues/<number> - Every PR must link to a meta issue — create one first if it doesn't exist
- Support PRs (targeting release branches) should not include release notes changes — release notes are auto-generated from the ticket description
- Release branches:
release/9.0,release/9.1,release/9.2,release/9.3,release/9.4— same fix is cherry-picked across all applicable branches
Use test-driven development (TDD):
- Write tests that define the expected behavior
- Run the tests — they should fail (confirms the test is meaningful)
- Implement the code
- Run the tests — they should now pass
Before submitting a feature PR, ensure:
- Docusaurus documentation — new features require docs in
docs/docusaurus/. The PR Preview bot auto-generates a preview atdocs.sequentech.io - Keycloak permissions — if adding new permissions, add them to the default tenant template in
keycloak.ts - Tests — add unit tests for new functions, including negative/edge-case tests (e.g., invalid input,
Nonevalues, parse errors) - Responsive UI — test frontend changes on different screen sizes
Recommended: VS Code Dev Containers or GitHub Codespaces. Services auto-start via Docker Compose with Nix/devenv.
Dev service URLs (inside dev container):
- Keycloak: http://127.0.0.1:8090 (admin/admin)
- Hasura: http://127.0.0.1:8080 (admin secret: "admin")
- Voting Portal: http://127.0.0.1:3000
- Admin Portal: http://127.0.0.1:3002
- ImmuDB: http://127.0.0.1:3325 (immudb/immudb)
- MinIO: http://127.0.0.1:9001
- RabbitMQ: http://127.0.0.1:15672
Dev container tips: When editing Rust code in harvest, windmill, or sequent-core, check the pod logs to see if it compiles successfully — the services auto-rebuild on changes inside the dev container.