Skip to content

Latest commit

 

History

History
195 lines (154 loc) · 10.4 KB

File metadata and controls

195 lines (154 loc) · 10.4 KB

Agent Instructions

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.

Project Overview

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.

Build Commands

Rust (from packages/)

cargo build                          # Build all Rust packages
cargo build -p <package>             # Build one package (e.g. braid, strand, windmill, sequent-core)
cargo build --release                # Production build

TypeScript (from packages/)

yarn                                 # 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 6006

Java (from packages/keycloak-extensions/)

mvn clean package                    # Build all Keycloak extensions
mvn clean verify                     # Build and test

Test Commands

Rust (from packages/)

cargo 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 --release

TypeScript (from packages/)

yarn --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 portal

Lint & Format

Rust (from packages/)

cargo fmt -- --check                 # Check formatting
cargo fmt                            # Fix formatting
cargo clippy                         # Lint

TypeScript (from packages/)

yarn lint                            # ESLint all frontend packages
yarn lint:fix                        # Auto-fix
yarn prettify                        # Check Prettier
yarn prettify:fix                    # Fix Prettier

License compliance

reuse lint                           # Every file must have SPDX headers

Architecture

Rust Packages (backend + WASM)

  • 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

TypeScript Packages (frontend)

  • 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)

Infrastructure

  • 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

Key Patterns

  • 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 with yarn 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

Important Conventions

  • 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-bindgen 0.2.104 — do not change
  • Forked crate: celery uses 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

Product Design Philosophy

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

Code Quality Standards

These are enforced during code review. Follow them to avoid revision requests.

Rust

  • Handle Option/Result properly — don't unwrap carelessly; return errors or use ? operator. Handle None cases explicitly rather than assuming values exist
  • Reuse types from sequent-core::types — never duplicate types that already exist in sequent-core (e.g., use sequent_core::types::ceremonies::CountingAlgType instead of creating local const &str equivalents)
  • 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/FromStr over string constants when representing fixed sets of values

TypeScript

  • No any types — always use proper types. If the type is known, use it; if not, define one
  • Async error handling — always await async calls and wrap them in try/catch where 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 relevant docker-compose files

General

  • 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

PR & Branch Conventions

  • Branch naming: feat/meta-<ticket>-<description>/main or fix/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

Development Workflow

Use test-driven development (TDD):

  1. Write tests that define the expected behavior
  2. Run the tests — they should fail (confirms the test is meaningful)
  3. Implement the code
  4. Run the tests — they should now pass

New Feature Checklist

Before submitting a feature PR, ensure:

  • Docusaurus documentation — new features require docs in docs/docusaurus/. The PR Preview bot auto-generates a preview at docs.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, None values, parse errors)
  • Responsive UI — test frontend changes on different screen sizes

Dev Environment

Recommended: VS Code Dev Containers or GitHub Codespaces. Services auto-start via Docker Compose with Nix/devenv.

Dev service URLs (inside dev container):

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.