Gentoo Elections ---------------- Welcome to the Gentoo Elections codebase. This handles all elections per the [Gentoo Elections](https://wiki.gentoo.org/wiki/Project:Elections) project. The Condercet system is used, and most of this repository exists just to house the actual data needed to run each election, such as the start/stop time, eligible voters, blank ballot etc. Completed elections are available in the `completed/` directory. The codebase is meant to be checked out somewhere read-only (Gentoo Infrastructure uses `/etc/elections/`), with the `votify` & `countify` scripts symlinked into somewhere used by $PATH for normal users (eg `/usr/local/bin`). `listify` & `election-stats-count` are other helpful tools. - `listify`: generate text to include in MOTD - `election-stats-count`: generate turnout stats for ongoing elections, for election officials to review an election in progress (put it in a cronjob, needs root). Instructions ------------ 1. Setup an election: --------------------- To create a new election, make a top-level directory with the exact name of the election. Usually in the format of `{council,trustees}-YYYYMM`. All of the following files should be in that directory. Let `${election_name}` be the name of the election. Any member of the elections project or infra may set this up. - `election-details`: key-value file with details about the election, see `election-details.template` `name`: exact election name `startDate`, `endDate`: start & end time in UTC `officials`: election officials, including the infra contact (prohibited from being candidates) `voters`: URL to list of members who may cast a ballot `ballot`: URL to sample ballot `url`: URL to the Elections page for this specific election (optional, newer) Using the above file, and the `populate-election.sh` script, the remaining files are created (pulling from URLs as needed.) - `Votify.pm`: symlink to `../Votify.pm` for tooling - `ballot-${election_name}` One entry per line, in alphabetical order. The special candidate `_reopen_nominations` is valid in some elections. The ballot order will be randomized per candidate, at voting time. - `officials-${election_name}`: list of election officials, including the infra contact - `start-${election_name}`: election start time, as epoch seconds. - `stop-${election_name}`: election end time, as epoch seconds. - `voters-${election_name}`: list of members who may cast a ballot For developers, the one liner, worked example below, run on woodpecker, can create the `voters` file. ``` ldapsearch -ZZ -x -w '' -S uid -LLL \ '(&(gentooStatus=active)(!(gentooAccess=infra-system.group)))' \ uid gentoojoin \ |awk -F ': ' '/uid:/ {print $2}' > voters-council-202406 ``` Some fine tuning to remove developers added to roll call after the cut off may be required. Populate the files, commit & push to Git. At the start time, an official should verify that the ballot works. Ideally a non-infra official, who then confirms to the infra election handler it worked. The URLs may link to either of two repos for the data: - `sites/projects/elections.git`, which populates: `https://projects.gentoo.org/elections/TYPE/YYYY/...` - `projects/elections.git` (this repo), which is only visible on Gitweb: https://gitweb.gentoo.org/proj/elections.git/ 2.1. Let people vote: ------------------- The regular way is to login to `dev.gentoo.org` and run `votify`. 2.2. Handle special ballots (optional) -------------------------------------- This step requires an infra contact. Some elections may have voters who cast ballots by irregular means: they should be accepted only via GPG-signed email to the election officials, who should agree that the signature is valid and matches a key that was already on a list prior to the election. The infra contact must place the ballot in `dev.gentoo.org:/home/$membername/.ballot-${election_name}-submitted` The elections mechanisms make no provision for truely secret ballot: election officials WILL see the content of the ballot. This is primarily a requirement for the Trustees election, which accepts ballots from all Foundation members. The roll of Foundation members includes active developers, retired developers, and other applicants to the Foundation Trustees. 3. Wait: -------- Just wait. `election-stats-count` runs every 30 minutes by cronjob, and prints status files into the home directories of election officials: `voter-turnout-${election_name}`. 4. Close of election: --------------------- This is the only step where the infra contact is absolutely required. 4.a. Automated "Close of election" ---------------------------------- Before the end of the election, the infra contact must run the script to schedule automated `countify --collect`: ``` $ sudo su # cd /etc/elections # ./infra-schedule-countify-collect ${election_name} ```` The job can be verified with: ``` # atq # at -c $JOB_ID ``` If the election closing time is modified, the old job MUST be deleted before the automated collection executes. ``` # atq # atrm $JOB_ID ``` 4.b. Manual "Close of election" ------------------------------- The infra contact must run `countify --collect ${election_name}` as root, which will write the master ballot & confirmation stub file to all officials: ``` $ sudo su # cd /etc/elections # ./countify --collect ${election_name} # find /home/${official}/results-${election_name}/ /home/${official}/results-${election_name}/master-${election_name} /home/${official}/results-${election_name}/confs-${election_name} ``` 5. Verify results: ------------------ Each election official should verify the results to collectively certify the results. This requires `countify --rank` to transform the master ballot into results. ``` $ cd /home/${official}/results-${election_name} $ countify --rank | tee ranked-${election_name} (election output) ``` 6. Email conf stubs: -------------------- ONE election official should use the mail-voters scripts to send confirmation stubs to each eligable voter. Note that this is ALL eligable voters, and not just those that cast a ballot. 7. Announce results: -------------------- The collected election officials should announce results; The email should include the output of `countify --rank`, as well as the master ballot for independent verification. 8. Cleanup: ----------- - The following files must be commited to `proj/elections.git` repo. - `master-${election_name}` - `casting-voters-${election_name}` - `ranked-${election_name}` - The some files should also be copied with renames into the `sites/projects/elections.git` repo as follows: - `ballot-${election_name}` -> `ballot-${election_name}.txt` - `master-${election_name}` -> `master-${election_name}.txt` - `ranked-${election_name}` -> `${election_name}-results.txt` - `voters-${election_name}.txt` -> `voters-${election_name}.txt` - `casting-voters-${election_name}` is a list of voters who cast a ballot, and needs to be recorded. This is required to purge rolls of inactive voters in some cases (Foundation members are required to vote at least every 2nd election if they are not an active developer). - The confirmation stub file `confs-${election_name}` MUST be destroyed after the election results have been formally accepted, to make de-anonymizing the ballots harder. - Lastly, `git mv` the election directory into the `completed/` directory.