This file provides repository guidance for AI coding agents working in this repository.
This is the canonical shared handbook for Claude, ChatGPT, GitHub Copilot coding agent, and similar tools.
For GitHub Copilot pull request reviews, review-specific guidance lives in .github/copilot-instructions.md and .github/instructions/*.instructions.md.
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.