aboutsummaryrefslogtreecommitdiff
blob: 856b1f9c767f4969eaaa547628241b957073a2bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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,
eligable 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`.

Let `${election_name}` be the name of the election. Any member of the elections
project or infra may set this up.

- `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.
- `election-details`:
  key-value file with details about the election.
  `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
- `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, works.
ldapsearch -ZZ -x -D uid=neddyseagoon,ou=devs,dc=gentoo,dc=org -W '(&(gentooStatus=active)(!(gentooAccess=infra-system.group)))' uid gentoojoin -LLL | grep "^uid" | sed -e "s/^uid: //" | sort -n > voters-council-202306.txt
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:
--------------------------
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 should 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.a. Automated "Close of election"
----------------------------------
Before the end of the election, 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
```

4.b. Manual "Close of election"
-------------------------------
This is the only step where the infra contact is absolutely required.
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.