Align uniWAHL production inputs and source controls with offline evaluation - #2335
Draft
edulix wants to merge 57 commits into
Draft
Align uniWAHL production inputs and source controls with offline evaluation#2335edulix wants to merge 57 commits into
edulix wants to merge 57 commits into
Conversation
|
# Conflicts: # docs/docusaurus/docs/01-system_introduction/01-system_introduction.md
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
The Vulnerability Disclosure Policy is the flaw remediation guidance addressed to TOE users (ALC_FLR.2.8C, work unit ALC_FLR.2-10) and is delivered together with ALC-05. Three points would have been visible to the evaluator comparing the two documents: - severity was scored with "CVSS v3.1 or later" while ALC-05 Section 7.2 classifies against v3.1 bands, leaving the published 30/60-day correction targets without a determinate scale; pinned to v3.1 - the "latest Release Notes" link pointed at release 9.3 while the certified TOE is v10.0.0 and main has moved to 9.4; the version-pinned link is replaced by a reference to the Releases section, which cannot go stale (the releases category has no index page to link to) - the "Try It Out" link resolved to a non-existent README.md, so the policy shipped with a broken link in the section that tells reporters where to test instead of against production; now points at 01-full-standalone-deployment.md Refs sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The scope named the public sequentech/step repository as the source of the SVP components and then described the uniWAHL source as living in "a separate, private repository". Read alongside ALC-01 and ALC-05, which place the implementation representation in the step repository of the CM system at SITE-01, this invited the question of which repository holds the TOE and whether it is under the described CM system. A disclosure policy does not need to state where source is kept. Scope is now expressed in terms of what reports are accepted for: the SVP components documented on the site, and the uniWAHL Version as delivered and documented, with source access explicitly not a precondition for reporting. Refs sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The sentence existed only to carry the link, so it is removed with it. Discoverability is unaffected: the lifecycle page links to this policy, and that direction is the useful one. Removing it also takes the lifecycle page out of the document set the policy reaches, which matters because that page states "emergency patches released within 24-48 hours for critical security issues" while this policy and ALC-05 Section 7.2 publish a 30-calendar-day correction target for critical severity. Two numbers for the same commitment, reachable from one another, is a question we do not need to be asked. Refs sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ached The policy promised "a public advisory once a fix is available" without saying where it appears, and separately said security-relevant changes are announced in the release notes - two statements a reader could not reconcile into one channel. Recognition compounded it by offering credit "in the security advisory and in the release notes", implying two publications. There is now one public channel, stated once: the public advisory for a fixed vulnerability is published in the release notes of the release containing the fix, with its content and the fact that it names no customer made explicit, and its date tied to the coordinated disclosure terms already stated above. Credit appears in that advisory. Direct notification now also says how a customer is reached - the contact registered for them when their release was delivered - which is the consumer register defined in ALC-07 Section 7.4. Refs sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reverts the rename to "customer". CC:2022 Part 3 uses "consumer" for the party a TOE is delivered to - ALC_DEL.1.1C speaks of "distributing versions of the TOE to the consumer" - so the evidence and this policy now use the standard's own word rather than a synonym. Refs sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ALC-05 Section 7.5 declares this page a configuration item and ALC-01 Section 4.2 identifies a controlled document by reference, version, path and commit. The page carried no version, so a copy under review - and it is delivered to the ITSEF as a printout, where the commit is invisible - could not be bound to one. Adds a version and date, and states that the published page is the authoritative copy, which a printout otherwise cannot convey. No approval record: this page is addressed to security researchers, and an internal table naming the reviewer would expose role structure for no assurance gain. Approval of each change is recorded in the CM system per ALC-05 Section 7.5, and the internal document reference is carried there rather than here. Refs sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nitions ALC-06 Section 2.5 and ALC-01 Section 7.2 require that a build definition name each base image by digest, so that the toolchain and runtime that produce an evaluated release cannot change under a mutable tag. Every external FROM in the production build definitions of the seven TOE parts now carries the index digest resolved from its registry today: rust:1.96.0-slim-bookworm, debian:bookworm, node:20-alpine, nginx:alpine, maven:3-amazoncorretto-17, maven:3-amazoncorretto-21, quay.io/keycloak/keycloak:26.6.1 The index digest is pinned rather than a per-platform manifest, so the existing multi-architecture builds keep working while the evaluated x86_64 build resolves to exactly one image. Tags are kept alongside the digests for readability; the digest is what the build resolves. Files: harvest, windmill, braid and b4 Dockerfile.prod; Dockerfile.prod; Dockerfile.keycloak; Dockerfile.cargo-packages; Dockerfile.prod-vstl- dependencies and -dependencies-build. The non-TOE Dockerfile.immudb* still use alpine:latest and are tracked on the internal to-do list. Refs sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sequent adopts CSAF 2.0 for security advisories (BSI TR-03183-2 section 8.1.14). provider-metadata.json describes Sequent as a CSAF publisher and names the security-contact OpenPGP key as the signing key; index.txt and changes.csv are the empty directory-distribution files until the first advisory. The CSAF field of security.txt follows when it is re-signed. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nd drop it from the TOE images The Miru results-transmission integration (ACM/EML transmission packages signed and encrypted with the external ECIES Java tool) is not part of the evaluated Sequent Voting Platform - uniWAHL Version. It is now compiled only with the new cargo feature `miru` of windmill, harvest, velvet and sequent-core: the consolidation modules that use the tool, the Miru ballot-image pipes, and the ECIES wrapper. Without the feature the three service entry points are stubs returning an error, so the Celery task registry and the HTTP routes compile unchanged and no cryptographic code of the integration is built. download_tally_tar_gz_to_file moves to consolidation::tally_download, which the template and PDF tasks use. The production build definitions of harvest and windmill no longer copy the committed ecies-tool.jar, download OpenJDK 22.0.2 from java.net, or pipe the cargo-binstall installer into a shell. The unused `ecies` crate is removed from the fips_core/fips_full features. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
cargo check of sequent-core, velvet, windmill and harvest passes with the default features and with --features miru; the lockfile loses the ecies crate and the libsecp256k1 family it pulled in, which no source used. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-256-CBC encrypt_file_aes_256_cbc / decrypt_file_aes_256_cbc used to start the openssl command with the password on the command line and OpenSSL's legacy EVP_BytesToKey (MD5, one iteration) derivation; the production images do not even install the openssl binary. They now run in-process on the openssl crate: PBKDF2-HMAC-SHA-256 with 600 000 iterations and a 64-bit random salt derives key and IV, AES-256-CBC with PKCS#7 padding encrypts, and the OpenSSL enc container (Salted__, salt, ciphertext) is kept so that exports still open with 'openssl enc -d -aes-256-cbc -pbkdf2 -iter 600000 -md sha256'. Decryption falls back to the legacy derivation for archives written by earlier releases. Known-answer tests use vectors produced by OpenSSL 3.0 for both derivations. The openssl crate is no longer optional; the shell helper of sequent-core is compiled only with the miru feature, its remaining user. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Check Rust format failed on aes_256_cbc_encrypt.rs after the PBKDF2 / AES-256-CBC export encryption landed. No behaviour change. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…peline Gating the Miru/ECIES integration behind a default-off feature left the mcballots fixture pipeline still declaring MCBallotReceipts, so every test walking that pipeline failed with "The Miru ballot-image pipes are not part of this build (feature `miru` is disabled)". get_config_mcballots now pushes that stage only under `miru`, so the fixture pipeline matches the build it runs in. The matching exec_next() in the blank-ballot pipeline test is gated the same way, and test_pipes_exec_mcballots - which exists to exercise the Miru pipeline and walks it stage by stage - is gated wholesale rather than half-disabled. Verified: test_blank_ballots_are_counted_across_the_full_pipeline passes in the default build, where it previously failed; cargo check and cargo fmt pass both with and without --features miru; the mcballots test still compiles and is collected under the feature. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The production job builds one image per part of the TOE from parts.toml. Four of those definitions could not be built at all. election-verifier had no build definition. It is the `verify` binary of the braid crate, which braid's own image carries as a second binary; the Security Target lists it as a part of its own, so it gets its own image, built by the same `cargo build --release --locked` and carrying only that binary. b4's definition was still b3's: it copied a ./b3 directory that no longer exists, built in /app/b3 with --features=server and installed a `server` binary as /usr/bin/b3. The crate is b4, its server feature is native and its binary is b4. harvest and windmill copied the same absent ./b3 and now copy ./b4, the workspace member they need to resolve Cargo.lock. Dockerfile.keycloak fetched the OID4VP extension archive with curl while building. The production job builds with --network=none, so that step could never run there. The download moves into its own stage, which the production build replaces with the accepted external input (--build-context oid4vp-src=<directory holding oid4vp.tar.gz>); a build outside that workflow still downloads it. Either way the archive is checked against OID4VP_SHA256 before it is unpacked. Verified on this machine (linux/arm64; the evaluated target is amd64, which would need emulation and was not built): the builder stage of election-verifier, b4, harvest and windmill each build and produce their binaries (verify, b4, harvest, main and beat); the oid4vp-build stage of Dockerfile.keycloak produces the same 772590-byte jar both by downloading the archive and with the archive supplied as a build context. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
packages/Cargo.toml carried [source.crates-io] replace-with = "vendored-sources" and [source.vendored-sources] directory = "vendor". Those are configuration keys, not manifest keys: cargo ignores them in a Cargo.toml, so nothing was ever vendored and every build resolved from crates.io. They move to packages/.cargo/config.toml, which cargo does read. Only the declaration of the source moves. A source that nothing replaces with is inert, so a checkout without packages/vendor still builds from crates.io as before; the replace-with lines that activate the directory are the [source] configuration `cargo vendor` prints, which arrives with the vendor directory from the controlled import of the external inputs. Those lines also cover the two pinned git forks, which the stanza in Cargo.toml never did. packages/vendor is ignored by git and left in the docker build context, which is how the offline production build reaches it. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…g it
The single-page applications depended on a committed tarball,
packages/<spa>/rust/sequent-core-0.1.0.tgz, built by hand in the devcontainer
and pinned in yarn.lock by its SHA-1. That tarball is a binary the production
build did not produce, and its hash is not reproducible: the same sources
packed on two machines give two hashes, which is why the check in
build_wasm.yml that would have compared them is commented out there.
packages/Dockerfile.prod now builds it. A wasm-toolchain stage carries
wasm-pack, wasm-bindgen (the version the wasm-bindgen crate pins), wasm-opt
and the wasm32-unknown-unknown standard library; the controlled production
build replaces that stage with the accepted external inputs
(--build-context wasm-toolchain=<dir>), and a build outside that workflow
downloads them. A wasm-build stage then runs wasm-pack on packages/sequent-core
and the node stage copies the resulting package into each rust/pkg directory
before yarn install.
The dependency becomes file:./rust/pkg, a directory. yarn records a directory
dependency without a content hash, so --frozen-lockfile holds however the
package was built, and yarn.lock stops being rewritten on every WASM rebuild.
The tarballs are deleted and rust/pkg is git-ignored.
Two feature definitions of sequent-core had to follow, because
--features=wasm,default_features did not build and, once it did, exported one
function of 52:
- wasm now pulls web-sys. The console_log! macro of util/console_log.rs calls
::web_sys::console under #[cfg(feature = "wasm")], so web-sys belongs to the
binding and not to the test harness; strand declares its own wasm feature
the same way.
- src/wasm/{areas,wasm}.rs, which hold the API the applications call, were
gated on wasmtest. They are gated on wasm now, and wasmtest keeps only what
its name says: strand/wasmtest, which adds the nine bench_* and test_*
functions. No application uses those.
Building sequent-core to WebAssembly is now a prerequisite of yarn install in
packages/, which the composite action .github/actions/build-sequent-core-wasm
performs. The devcontainer scripts copy the package into place instead of
repacking a tarball and rewriting yarn.lock. The three GitHub workflows that
run yarn install have to call that action; that change is held back because
the credentials available here have no workflow scope.
Verified on this machine (linux/arm64): wasm-pack with wasm,default_features
produces a 1431588-byte module exporting 43 functions - the 52 of the
committed tarball minus the nine bench_* and test_* ones - and with
wasmtest,default_features still produces all 52; the ballot-verifier and
voting-portal images build from Dockerfile.prod through
yarn install --frozen-lockfile and serve that same module.
Related: sequentech/meta#10548
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…the network The two Maven stages of Dockerfile.keycloak resolved from Maven Central while building, which the production job's --network=none forbids. A maven-repository stage, empty by default, is what they copy into /root/.m2/repository; the controlled production build replaces it with the local repository `prepare vendor` fills (--build-context maven-repository=<dir>), and a build outside that workflow resolves from the network as before. The spis-build stage also installed findutils with dnf, for two `find` invocations that shell globbing does with the same result: the target directories are removed by path, and the provider jars are collected by iterating over the module target directories, skipping original-*.jar and *-tests.jar as before. Verified on this machine (linux/arm64): the spis-build stage produces the same thirteen provider jars, including the one from the beyond extensions, and the whole image builds with all fourteen providers in /opt/keycloak/providers. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…inaries The wasm-toolchain stage of packages/Dockerfile.prod handed the build stage a directory of extracted binaries, so the accepted external input would have been a tree assembled on the workstation rather than something a publisher signs and serves. It now carries the four archives as published - wasm-pack, wasm-bindgen, binaryen and the wasm32-unknown-unknown standard library - and the wasm-build stage extracts them. Their digests are pinned in the CM system's inputs configuration and verified at import, which is where every other external input's digest lives. Verified on this machine (linux/arm64), both ways: downloading the archives and with them supplied as the build context, wasm-pack 0.15.0, wasm-bindgen 0.2.104 and wasm-opt 123 produce the same 1431588-byte module with 43 exports. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
packages/.cargo/config.toml patched auto_generate_cdp to a git fork at version 0.4.4, while Cargo.lock resolves 0.4.5 from crates.io and recorded the fork as [[patch.unused]]. The patch was dead, and it broke the offline production build before anything compiled: cargo fetches the git source of a patch to evaluate it even when the resolution does not use it, and --network=none has no github.com. The patch and its [[patch.unused]] block are removed; the lockfile is otherwise unchanged (cargo metadata rewrote nothing else). Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…accepted inputs The production build runs with --network=none (ALC-06, Section 2.5), and the build definitions still fetched at three places: apt-get in every builder and runtime stage of harvest, windmill, braid, b4 and election-verifier and in the wasm-build stage of Dockerfile.prod, apk add in its nginx stage, and - though the production job placed the vendored crates in the checkout - cargo and yarn inside the containers, because a docker build context does not follow a symlink out of the context and no definition copied the vendor directory or an offline mirror. Every such input now has a stage the production build replaces with `--build-context <stage>=<directory>` from the accepted inputs, the pattern the OID4VP archive, the Maven repository and the WebAssembly toolchain already use: - `debs-<stage>` / `apks-nginx`: FROM scratch, filled by a download stage that runs the package manager of the base image with `--download-only` (apt) or `apk fetch --recursive`. The install step runs `apt-get install /tmp/debs/*.deb` or `apk add --no-network /tmp/apks/*.apk` from local files, with no `apt-get update`. Outside the production workflow the download stage runs and the result is what it was: apt authenticates the packages against the keyring of the base image, apk verifies the signature each .apk carries when it installs it. chromium still comes from bookworm-proposed-updates, in the download stage. - `cargo-vendor`: FROM scratch, `COPY --from=cargo-vendor / ./vendor/`, where the [source] configuration the production job appends to .cargo/config.toml points. Empty outside the workflow, so cargo resolves from crates.io as before. - `yarn-offline-mirror`: FROM scratch; the node builder writes a .yarnrc naming it. Empty outside the workflow, so yarn fetches as before. curl and unzip leave the braid builder, where nothing used them, together with the debian-archive-keyring reinstall; a duplicated COPY of the trustee binary goes too. The AWS CLI and Vault CLI stanza of the braid and b4 runtime stages is unchanged and is the last network retrieval left; curl and unzip stay in those runtime packages for it. The wasm-build stage installs the wasm32 standard library with the archive's own install.sh into the toolchain's sysroot. The previous tar extraction landed one directory too deep (a dirname of `--print target-libdir` too few), so wasm-pack had rustup download the target over the network, which is why the earlier verification of that stage passed. Verified on linux/arm64 with the exported download stages as contexts: all twelve export; the harvest runtime set installs offline and `chromium --version` runs; jq installs offline in the nginx stage; election-verifier builds end to end under --network=none with its three contexts; ballot-verifier builds end to end under --network=none with its five (yarn fetched 2527 packages from the mirror, the three webpack builds ran, the image serves the module). Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six package.json files declared webpack as exactly 5.94.0 while the root `resolutions` field forces ^5.94.0 and packages/yarn.lock resolves 5.105.1, so the declared version was never the one installed. They now declare ^5.94.0, the same range as the resolution, and the lockfile drops the `webpack@5.94.0` key nothing requests any more; nothing else in it changes, and `yarn install --frozen-lockfile --offline` passes from the offline mirror. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…main ALC-06 controls `unsafe` by rule: permitted only where an FFI boundary or a documented performance need requires it, each use under a // SAFETY: comment, the count reported by the required checks. The compiler can hold most of that rule for us. Every crate of the workspace now carries `[lints.rust] unsafe_code = "forbid"` in its manifest, as windmill already did, so that a build fails on an unsafe item; braid, whose browser storage under the `wasm` feature needs `unsafe impl Send`/`Sync` for a RefCell that WASM's single thread never shares, sets `deny` and allows those two impls where they stand, under the SAFETY comment they already had. The three unsafe blocks of sequent-core's render_pdf example were unnecessary: the workspace is edition 2021, where env::set_var is a safe function. They are gone and the crate forbids unsafe like the others. scripts/check-unsafe.py reports every `unsafe` token outside comments and strings, per crate, with the crate's lint and whether a SAFETY comment precedes it, and fails on a crate without the lint or a use without the comment. Generated bindings - plugins/miru/src/bindings.rs, wit-bindgen output for the Miru plugin, which is not part of the TOE - are listed as such and not held to the comment rule. The controlled workflow runs the script as its unsafe-report check. `cargo check --workspace` passes with the lints for every lib, bin, test and bench, and sequent-core also with the `wasm` feature: the #[wasm_bindgen] expansions do not trip `forbid`. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…llows `N <= 0` and `width <= 0` on usize can only be true when the value is 0; clippy's absurd_extreme_comparisons denies the form by default, which made every `cargo clippy` run of the crate an error. `== 0` says the same thing. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…name B4 scripts/tasks/dependencies/generate-dependency-report.sh wrote to docs/docusaurus/docs/reference/third_party_deps/, a path that does not exist; the reference lives under 05-reference/, so the report has not been regenerated since the move and its section for the bulletin board is still headed B3, a component that no longer exists. The paths follow the tree, the section is B4 with a one-line description, and the scanner is repaired on the three points that a run showed: it identifies itself to crates.io with a User-Agent and paces its requests at one per second, as crates.io requires (403 and 429 otherwise); a dependency inherited from the workspace (`workspace = true`) takes its version from [workspace.dependencies] instead of N/A; a crate renamed with `package = "..."` is looked up under its published name; and a `file:` package is this repository's own artifact, not a third party. The data itself is regenerated separately. Related: sequentech/meta#10548 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…puts Use persistent trustee configuration by default; explicitly opt into ephemeral test keys. Preserve existing keys on cloud lookup failure and avoid tracing secret contents. Remove runtime CLI downloads; optional reviewed cloud tools enter through a build context. Cargo, Maven and Yarn production invocations require offline resolution. Validation: five entrypoint tests in offline Ubuntu 26.04 containers, shell syntax, empty cloud build-context experiment. Full evaluated-platform builds remain tracked under the ALC completion plan. Related: sequentech/meta#10548
Calculate ranked bases after conversion to u64 and check the cumulative increment. Propagate errors through base construction and raw-ballot encoding instead of wrapping or panicking on extreme contest settings. Preserve the release overflow profile. Validation: 61 ballot-codec tests passed (one existing ignored test); boundary regression also passed in the optimized release profile. Removed a misplaced blank line diagnosed by Clippy. Related: sequentech/meta#10548
Validated with the actual extensions and OID4VP build using Maven offline and build-step networking disabled on arm64. Related: sequentech/meta#10548
Declare the B4 test dependency and PDF example features, preserve tracing argument redaction, and make JSON configuration write behavior explicit. Resolve correctness/suspicious Clippy diagnostics without changing the strict warning gate. Related: sequentech/meta#10548
Write tally values under their named columns, include the added execution/blank-ballot fields, and propagate output or schema errors. Apply the preview status to the serialized election copy. Remove an undeclared, unreachable COPY feature implementation and resolve selected compiler diagnostics without changing the production lint gate. Related: sequentech/meta#10548
User-supplied offsets beyond the returned list and offset-plus-limit overflow could panic. Use one bounded slice helper, retain total counts, and cover ordinary, empty and usize::MAX cases. Remove six no-op reference clones without changing ownership. Related: sequentech/meta#10548
…lures Retain the existing token login/logout protocol with statement-scoped deprecated expectations; changing board/audit callers to sessions requires a separate protocol review. Add real HTTP/2 transport regressions for credential diagnostics, authentication headers, transactions, and rejected deletion. Related: sequentech/meta#10548
Filter direct and inherited assignments at every tree level; empty and unknown selections produce no matches. Three regression tests reproduce unrelated contest leakage before the change and pass afterward. Related: sequentech/meta#10548
…ations Keep client credentials on the wire while redacting token Debug, trace arguments, request bodies and token decode failures. Propagate unsuccessful credential/localization HTTP responses. Five local HTTP/token contract tests pass; all four original regression cases fail before correction. Related: sequentech/meta#10548
Reject malformed plaintext length, exhausted radix capacity, zero radices and a non-progressing fallback; preserve finite radix-one positions. Bound report successor indexes and complete temporary-file writes. Resolve remaining scoped diagnostics, preserving existing public API shapes with per-item lint expectations whose reasons are retained for the PR. Related: sequentech/meta#10548
Restore the feature-specific Velvet helper for optional Miru compilation. Preserve item-level API style justifications and existing task serialization. Related: sequentech/meta#10548
Preserve request formats, SQL parameter order and existing command interfaces while removing dormant code and separating test helpers. Related: sequentech/meta#10548
Retain mock/input wire fields, equivalent copy and error formatting, and supply the existing optional S3 filename argument in the alternate renderer. Related: sequentech/meta#10548
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Aligns uniWAHL source and production definitions with the offline build and CM procedures in the companion ALC/tooling PR.
The production definitions identify seven TOE parts, pin base images, consume prepared OS/Cargo/Yarn/Maven/Wasm inputs and build first-party WebAssembly from source. The evaluated configuration excludes Miru-specific integration and gates AWS/Vault CLI use while retaining S3-compatible storage and Chromium. Selected source fixes cover tally CSV columns, serialized preview publication status and bounded role/permission pagination. Offsets beyond the returned list now produce an empty page; large limits return the remaining entries without slicing panics. Existing authorization and total counts are preserved.
The public documentation build records exact source/output identities for policy, key, signed security.txt and CSAF metadata. The consumer exporter selects explicit handbook articles/local raster assets, rewrites selected-page links and refuses stale, missing or unsupported content. It checks large committed Git objects without buffering their contents. The branch also retains earlier export-encryption helper and public vulnerability-reporting documentation changes.
Source corrections also keep immudb/Keycloak credentials out of diagnostics and propagate rejected deletion, authentication and localization operations. Area-contest selection now honors requested IDs while preserving inherited assignments. Ballot decoding rejects malformed length/radix bounds, report successor indexes cannot overflow, and temporary-file writes complete their buffers.
Validation: Strand passes strict all-targets Clippy and 27 library tests in both default and rayon configurations. immudb-rs passes strict all-targets Clippy and two real HTTP2/gRPC transport tests; both tests fail against the original client for the demonstrated defects. The Keycloak correction passes five HTTP/token contract tests; all four original regression cases fail before correction. Responses are synthetic, with actual transmitted form/authorization/header values checked.
Sequent-core passes strict all-targets Clippy with workspace-selected features, 284 library tests, three area tests, eight decoder tests and two report-boundary tests. Two existing tests remain ignored. The same final test binary passes the actual Chromium PDF case in a disconnected, restricted Debian arm64 container; its existing code disables the browser internal sandbox. Five decoder cases and the report overflow reproduce before correction. Earlier validated CSV/preview and pagination fixes are retained. Electoral-log and the error-adapter macro pass strict all-targets Clippy; all 10 electoral-log unit tests pass. Its existing database integration test also passes against actual immudb 1.9.6 in a disposable disconnected container, exercising database creation, message insertion/retrieval/filtering and deletion. B4 passes strict all-targets Clippy with native/client features and all three serialization tests; its two existing PostgreSQL integration tests remain ignored. Braid passes strict all-native-targets Clippy and its existing 1,000-ballot in-memory protocol test, including key generation, shuffles, proof checks and plaintext agreement. Its HTTP/PostgreSQL/S3 integration remains unrun. Velvet passes strict all-targets Clippy, 73 library tests and 36 runoff integration tests in the isolated Debian arm64 Chromium container; the CLI help invocation also succeeds. The 299-second suite includes actual PDF rendering; its fixtures delete generated outputs. The CLI now uses the existing library modules, unused runtime/computations are removed, and equivalent slice, option, ordering and pinned-Rand API cleanup preserves tally formulas. Windmill passes strict all-targets Clippy, 326 library tests and two maintained Celery contract tests. Its malformed vault-key parser now returns fixed errors; the same regression tests reproduce the old panic and pass after correction. Two existing library tests remain ignored. The restricted, disconnected native test run uses an embedded earlier PDF fixture, with no new browser launch. Optional Miru compilation passes after restoring its feature-only Velvet helper; it retains existing warnings. Complete workspace formatting passes. Harvest, step-cli and immu-board pass strict all-targets Clippy. All nine Harvest SQL/structured-response tests and both CLI cast-vote export tests pass in a disconnected native container; the existing election-environment test remains ignored. Synthetic configuration supplies the expected SQL limits, without database connections. Harvest also compiles with optional Miru enabled. The complete workspace now passes strict Clippy for all native targets of all 17 members and the full format check. The renderer’s alternate AWS variant also compiles after correcting a stale optional S3 argument. Exact source, selected features, compiler identity and logs are retained. Actual workflow/target production checks remain open.
The new Tokio test dependency and immudb transport-test dependency edges use existing locked versions, with no package upgrades. These metadata changes require a fresh controlled preparation request before production.
Item-specific lint expectations and SDLC §3.2 justifications
The immudb login statement retains token authentication required by existing board/audit callers; migration to sessions is a separate protocol change. Its logout statement must invalidate the token issued by that retained API. Both use statement-scoped
#[expect(deprecated)].The following
#[expect]attributes address only the identified style diagnostic while preserving the existing interface. No blanket suppression or production-gate change is introduced.ballot.rs::CandidatesIconCheckboxPolicynon_camel_case_typesballot.rs::WeightedVotingPolicynon_camel_case_typesballot.rs::ConsolidatedReportPolicynon_camel_case_typestypes/hasura/extra.rs::TasksExecutionStatusnon_camel_case_typesballot_style.rs::create_ballot_styleclippy::too_many_argumentsservices/keycloak/user.rs::list_usersclippy::too_many_argumentsservices/keycloak/user.rs::edit_userclippy::too_many_argumentsservices/keycloak/user.rs::edit_user_with_credentialsclippy::too_many_argumentsservices/s3.rs::upload_multipart_data_to_s3clippy::too_many_argumentssqlite/results_area_contest.rs::update_results_area_contest_documents_sqliteclippy::too_many_argumentssqlite/results_election_area.rs::create_results_election_area_sqliteclippy::too_many_arguments|
electoral-log/client/board_client.rs::get_electoral_log_messages_filtered|clippy::too_many_arguments| Preserve the existing query API with explicit database, time bounds, filters, ordering and pagination ||
electoral-log/client/board_client.rs::get_filtered|clippy::too_many_arguments| Keep the internal query implementation aligned with the existing filtered-message API ||
electoral-log/messages/message.rs::external_api_request_message|clippy::too_many_arguments| Preserve the external API audit constructor with explicit signed event, operation and voter context ||
electoral-log/messages/message.rs::external_reconciliation_message|clippy::too_many_arguments| Preserve explicit reconciliation identity, sequence, timestamps, hashes and signing context ||
electoral-log/messages/message.rs::cast_vote_message|clippy::too_many_arguments| Preserve the existing signed vote-event constructor and its voter, network and area context ||
electoral-log/messages/message.rs::cast_vote_with_channel_message|clippy::too_many_arguments| Preserve the channel-aware signed vote-event constructor and its existing caller contract ||
electoral-log/messages/message.rs::cast_vote_message_from_body|clippy::too_many_arguments| Keep both vote-event constructors on the same explicit body, signing and audit-context path ||
electoral-log/messages/message.rs::cast_vote_error_message|clippy::too_many_arguments| Preserve the existing signed vote-error constructor and its voter, network and area context ||
electoral-log/messages/message.rs::voter_public_key_message|clippy::too_many_arguments| Preserve the public-key audit constructor with explicit tenant, event, voter and signing context ||
electoral-log/messages/message.rs::from_body|clippy::too_many_arguments| Keep statement signing and the existing optional audit metadata explicit for all message constructors ||
electoral-log/messages/message.rs::sign|clippy::too_many_arguments| Preserve the dual-signature message API with explicit signing keys and optional audit metadata ||
b4/db.rs::insert_message|clippy::too_many_arguments| Preserve the existing message storage API with explicit payload, storage location and signed statement metadata ||
braid/bin/demo_tool.rs::post_ballots|clippy::too_many_arguments| Keep the demo ballot-posting helper aligned with its database, object storage and protocol configuration inputs ||
velvet/cli/mod.rs::cli|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/config/mod.rs::config|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/fixtures/mod.rs::fixtures|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/ballot_images/mod.rs::ballot_images|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/decode_ballots/mod.rs::decode_ballots|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/do_tally/counting_algorithm/mod.rs::counting_algorithm|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/do_tally/mod.rs::do_tally|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/generate_db/mod.rs::generate_db|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/generate_reports/mod.rs::generate_reports|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/mark_winners/mod.rs::mark_winners|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/pipes/mod.rs::pipes|clippy::module_inception| Preserve the existing module layout, re-exports and caller paths during the construct review ||
velvet/fixtures/fixtures.rs::create_area_config|clippy::too_many_arguments| Keep the fixture API explicit about tenant, election, area, census and audit counts ||
velvet/pipes/do_tally/tally.rs::create_candidate_results|clippy::too_many_arguments| Preserve the existing tally-result API and its explicit vote-count and percentage inputs ||
velvet/pipes/do_tally/tally.rs::create_contest_result|clippy::too_many_arguments| Preserve the existing contest-result API and its explicit process, candidate and ballot totals ||
velvet/pipes/generate_reports/generate_reports.rs::read_breakdowns|clippy::too_many_arguments| Keep report breakdown scope, names, result paths and inclusion decisions explicit ||
velvet/pipes/generate_reports/generate_reports.rs::make_report|clippy::too_many_arguments| Preserve the report assembly interface with explicit election, contest, area and tally-sheet context ||
velvet/pipes/generate_reports/generate_reports.rs::write_report|clippy::too_many_arguments| Preserve the report output interface with explicit scope, formats, hashes and consolidation controls |The Windmill cleanup adds these 76 scoped expectations. The single
create_ballot_receipttask module also covers its generated constructor.windmill/src/types/documents.rs::EDocumentsnon_camel_case_typeswindmill/src/types/documents.rs::ETallyDocumentsnon_camel_case_typeswindmill/src/types/tasks.rs::ETasksExecutionnon_camel_case_typeswindmill/src/postgres/application.rs::insert_applicationclippy::too_many_argumentswindmill/src/postgres/application.rs::update_application_statusclippy::too_many_argumentswindmill/src/postgres/ballot_style.rs::insert_ballot_styleclippy::too_many_argumentswindmill/src/postgres/cast_vote.rs::insert_cast_voteclippy::too_many_argumentswindmill/src/postgres/document.rs::insert_documentclippy::too_many_argumentswindmill/src/postgres/document.rs::insert_document_with_annotationsclippy::too_many_argumentswindmill/src/postgres/keys_ceremony.rs::insert_keys_ceremonyclippy::too_many_argumentswindmill/src/postgres/results_area_contest.rs::update_results_area_contest_documentsclippy::too_many_argumentswindmill/src/postgres/results_election_area.rs::insert_results_election_area_documentsclippy::too_many_argumentswindmill/src/postgres/tally_results_publication.rs::validate_new_publication_sourceclippy::too_many_argumentswindmill/src/postgres/tally_session.rs::insert_tally_sessionclippy::too_many_argumentswindmill/src/postgres/tally_session_contest.rs::insert_tally_session_contestclippy::too_many_argumentswindmill/src/postgres/tally_session_execution.rs::insert_tally_session_executionclippy::too_many_argumentswindmill/src/postgres/tally_sheet.rs::insert_tally_sheetclippy::too_many_argumentswindmill/src/postgres/tally_sheet_import.rs::insert_tally_sheet_importclippy::too_many_argumentswindmill/src/postgres/tasks_execution.rs::insert_tasks_executionclippy::too_many_argumentswindmill/src/services/application.rs::verify_applicationclippy::too_many_argumentswindmill/src/services/application.rs::get_filter_from_applicant_dataclippy::too_many_argumentswindmill/src/services/application.rs::confirm_applicationclippy::too_many_argumentswindmill/src/services/application.rs::reject_applicationclippy::too_many_argumentswindmill/src/services/ballot_styles/ballot_style.rs::create_ballot_style_postgresclippy::too_many_argumentswindmill/src/services/cast_votes.rs::get_count_votes_per_dayclippy::too_many_argumentswindmill/src/services/cast_votes.rs::get_count_votes_per_day_from_relationclippy::too_many_argumentswindmill/src/services/ceremonies/insert_ballots.rs::insert_ballots_messagesclippy::too_many_argumentswindmill/src/services/ceremonies/keys_ceremony.rs::create_keys_ceremonyclippy::too_many_argumentswindmill/src/services/ceremonies/result_documents.rs::process_and_upload_documentclippy::too_many_argumentswindmill/src/services/ceremonies/result_documents.rs::save_documentsclippy::too_many_argumentswindmill/src/services/ceremonies/result_documents.rs::save_result_documentsclippy::too_many_argumentswindmill/src/services/ceremonies/result_documents.rs::save_area_documentsclippy::too_many_argumentswindmill/src/services/ceremonies/results.rs::generate_results_id_if_necessaryclippy::too_many_argumentswindmill/src/services/ceremonies/results.rs::process_results_tablesclippy::too_many_argumentswindmill/src/services/ceremonies/results.rs::populate_results_tablesclippy::too_many_argumentswindmill/src/services/ceremonies/tally_ceremony.rs::create_tally_ceremonyclippy::too_many_argumentswindmill/src/services/ceremonies/velvet_tally.rs::create_election_configs_blockingclippy::too_many_argumentswindmill/src/services/ceremonies/velvet_tally.rs::run_velvet_tallyclippy::too_many_argumentswindmill/src/services/certificate_authority.rs::import_certificate_authorityclippy::too_many_argumentswindmill/src/services/certificate_authority.rs::delete_certificate_authorityclippy::too_many_argumentswindmill/src/services/consolidation/eml_generator.rs::render_eml_fileclippy::too_many_argumentswindmill/src/services/documents.rs::upload_and_return_documentclippy::too_many_argumentswindmill/src/services/documents.rs::upload_and_return_document_with_annotationsclippy::too_many_argumentswindmill/src/services/documents.rs::upload_and_return_document_innerclippy::too_many_argumentswindmill/src/services/documents.rs::upload_and_return_public_event_documentclippy::too_many_argumentswindmill/src/services/documents.rs::get_upload_urlclippy::too_many_argumentswindmill/src/services/election_event_status.rs::update_election_voting_status_implclippy::too_many_argumentswindmill/src/services/electoral_log.rs::for_admin_userclippy::too_many_argumentswindmill/src/services/electoral_log.rs::post_admin_pkclippy::too_many_argumentswindmill/src/services/electoral_log.rs::post_cast_voteclippy::too_many_argumentswindmill/src/services/electoral_log.rs::post_cast_vote_errorclippy::too_many_argumentswindmill/src/services/electoral_log.rs::post_external_api_requestclippy::too_many_argumentswindmill/src/services/electoral_log.rs::post_external_reconciliationclippy::too_many_argumentswindmill/src/services/external/api_datafix.rs::replace_voter_pinclippy::too_many_argumentswindmill/src/services/insert_cast_vote.rs::try_insert_cast_voteclippy::too_many_argumentswindmill/src/services/insert_cast_vote.rs::insert_cast_vote_and_commitclippy::too_many_argumentswindmill/src/services/insert_cast_vote.rs::check_status_with_loaded_electionclippy::too_many_argumentswindmill/src/services/insert_cast_vote.rs::check_statusclippy::too_many_argumentswindmill/src/services/insert_cast_vote.rs::check_previous_votesclippy::too_many_argumentswindmill/src/services/protocol_manager.rs::add_ballots_to_boardclippy::too_many_argumentswindmill/src/services/reports/template_renderer.rs::execute_report_innerclippy::too_many_argumentswindmill/src/services/reports/template_renderer.rs::execute_reportclippy::too_many_argumentswindmill/src/services/tally_sheet_import/application.rs::preview_tally_sheet_importclippy::too_many_argumentswindmill/src/services/tally_sheet_import/application.rs::create_tally_sheet_importclippy::too_many_argumentswindmill/src/services/voting_status.rs::update_election_statusclippy::too_many_argumentswindmill/src/services/voting_status.rs::update_board_on_status_changeclippy::too_many_argumentswindmill/src/tasks/mod.rs::create_ballot_receipt (single generated task)clippy::too_many_argumentswindmill/src/tasks/execute_tally_session.rs::process_plaintextsclippy::too_many_argumentswindmill/src/tasks/execute_tally_session.rs::upsert_ballots_messagesclippy::too_many_argumentswindmill/src/tasks/execute_tally_session.rs::map_plaintext_dataclippy::too_many_argumentswindmill/src/tasks/execute_tally_session.rs::execute_tally_session_wrappedclippy::too_many_argumentswindmill/src/tasks/generate_reconciliation_patches.rs::write_envelope_tailclippy::too_many_argumentswindmill/src/tasks/send_template.rs::on_success_send_messageclippy::too_many_argumentswindmill/src/tasks/send_template.rs::send_template_email_or_smsclippy::too_many_argumentswindmill/src/services/ess_xml_converter.rs::resolve_contest_max_votesclippy::result_large_errwindmill/src/services/vault/mod.rs::vaultclippy::module_inceptionThe CLI cleanup preserves three existing argument lists and one serialized tally-status enum:
step-cli/src/commands/create_applications.rs::set_applicationsclippy::too_many_argumentsstep-cli/src/commands/export_election_event.rs::export_election_eventclippy::too_many_argumentsstep-cli/src/commands/update_voter.rs::edit_voterclippy::too_many_argumentsstep-cli/src/types/tally.rs::TallyExecutionStatusclippy::upper_case_acronymsThe pinned Celery code generator now emits its existing task implementation inside an anonymous constant, removing the repeated
non_local_definitionsfailure. The vendored 0.5.5 source records the exact upstream revision, license and pre-patch hashes; the runtime revision and all dependency versions stay unchanged. The same minimal consumer rejects the original macro and passes two tests after the patch, covering task metadata/options, JSON arguments and generated sync/async success/error behavior. The maintained test lives in Windmill. This changes dependency source identity and requires fresh controlled intake before Site import; broker dispatch remains unverified. All 15 Dockerfiles that copy the workspace manifest now include the vendored directory; a reconstructed production Rust context passes locked offline dependency resolution after the addition.Five public-build tests, nine consumer-export tests and a clean frozen offline-install documentation build from the development cache pass, with existing broken-link warnings elsewhere in the public site. Actual AGD selections require content review; no handbook approval or site publication is asserted. The checks run on arm64 and do not establish complete seven-part x86_64 production. Exact evidence and current status are maintained in the Internal To Do record.
The public GitHub workflow patch remains on local branch
wasm-workflowsand in a patch file because the available credential lacks workflow scope; it is not in this PR. The carried dependency CSV is excluded from this continuation's scoped commits. Miru packaging and non-TOE image cleanup remain separate work.Related: https://github.com/sequentech/meta/issues/10548