← System Documentation Getting started

Complete E-Voting system manual

End-to-end reference for platform setup, elections, voting, results, disputes, security, records and maintenance.

CivitasVote Complete System Manual

Document purpose and status

This manual describes the behaviour implemented in the CivitasVote source reviewed and integrated on 24 July 2026. It is written for organisations that must install, configure, operate, audit and support an election without depending on the original developers. It explains the normal workflow, the authority boundaries, each important form field, the data handled by the system, and the conditions that prevent an unsafe action.

CivitasVote is an application-level election platform for associations, unions, societies, schools, professional bodies and similar membership organisations. It provides controlled voter-register preparation, nominations, anonymous ballot storage, tallying, approval, reporting and audit records. It does not replace the organisation's constitution, electoral regulations, data-protection obligations or independent election assurance.

The following statements are especially important:

  1. A technical user account does not automatically confer election authority.
  2. An election-officer appointment applies only to the named election cycle and appointment period.
  3. Committee appointment is independent of voter eligibility. An officer may be appointed without being on the voter register, and an otherwise eligible officer is not automatically prevented from voting.
  4. Accepted ballot selections are stored without a voter foreign key. The voter register retains participation status but not the voter's choices.
  5. The platform is not a coercion-resistant or end-to-end verifiable cryptographic voting protocol. Infrastructure, endpoint and governance controls remain necessary.

1. System map

CivitasVote is organised into the following functional areas.

Area Purpose
Accounts Email-based sign-in, temporary-password enforcement and login security state.
Platform Control Centre User accounts, Platform Administrator appointments, associations, association governance assignments and the global election-officer register.
Associations Organisation-specific landing pages and isolation of association data.
Elections Election-cycle configuration, committee appointments, positions, results, declarations, objections and officer complaints.
Voters Reusable member identities, election-specific eligibility, register imports, certification and voting credentials.
Nominations Self-nomination, vetting, candidate photographs, candidate imports and final candidate-list publication.
Ballot box Voter verification, ballot presentation, anonymous ballot submission, receipts and tally input.
Notifications Queued email and SMS delivery.
Audit log Append-only, hash-chained event records.
Help Centre Public voter guidance for eligibility, verification, ballots, receipts, privacy and accessibility.
System Documentation Role-aware operational manuals for administrators, commissioners, election officers, auditors and technical operators.

The main public and protected URL groups are:

  • / — public home page;
  • /dashboard/ — authenticated dashboard;
  • /control-centre/ — platform and association administration;
  • /organisations/ — association pages;
  • /elections/ — election operations and public results;
  • /voters/ — voter-register operations;
  • /nominations/ — nomination and candidate-register operations;
  • /vote/ — voter-facing election, verification, ballot and receipt pages;
  • /help/ — public voter Help Centre;
  • /help/docs/ — authenticated role-aware System Documentation;
  • /admin/ — Django Admin, restricted to the technical superuser.

2. Core security and governance principles

2.1 Separation of accounts and authority

The accounts.User record is only an application account. Authority is granted separately through one of the following records:

  • PlatformRoleAssignment for a Platform Administrator;
  • OrganisationMembership for association governance;
  • ElectionCommitteeMembership for a role in a particular election cycle.

An ordinary user may hold several election appointments over time, but each election requires its own appointment record. A later election does not inherit an earlier appointment.

2.2 Technical superuser

The technical superuser is the only user permitted to enter Django Admin. This account is intended for installation, recovery and exceptional technical administration. Routine association and election work should be performed through the application interfaces.

2.3 Platform Administrator

A Platform Administrator can create and manage ordinary users, associations and association-governance assignments. The appointment has a reference, start and end time, and may be revoked or reinstated. Platform authority does not by itself allow a person to operate the ballot or approve results.

2.4 Association governance

The active association roles in the Control Centre are Organisation Owner and Organisation Administrator. The model also defines Election Manager, Voter Data Officer, Auditor and Read-only Viewer, but the current governance-assignment form exposes only Owner and Administrator. Owners and Administrators create election cycles and appoint election officers; they do not automatically obtain operational election authority.

2.5 Election officers

The minimum committee contains three distinct people:

  1. Electoral Commissioner / Chairperson;
  2. Election Secretary;
  3. ICT and Data Protection Commissioner.

Other roles are optional:

  • Deputy Commissioner;
  • Gender and Inclusion Commissioner;
  • Electoral Appeals Panel Chairperson;
  • Electoral Appeals Panel Member;
  • Committee Member;
  • Returning Officer;
  • Voter Registration Officer;
  • Polling or Verification Officer;
  • Observer;
  • Election Auditor.

The same user cannot serve on both the Commission and the Appeals Panel for the same cycle. Only one active Commissioner is allowed. Optional Commission offices and the Appeals Chair are also limited to one active holder each by readiness validation.

Every active appointment requires:

  • an active CivitasVote user account;
  • an official appointment reference;
  • an appointment start date and time;
  • an appointment end date and time;
  • a PDF appointment letter, maximum 5 MB.

For readiness, each appointment must begin no later than the start of the election process and continue until at least three days after the voting close. The process start is the nomination opening time where self-nomination is enabled; otherwise it is the voting opening time.

2.6 Appointment access lifecycle

An appointment may be:

  • Future — start date has not arrived;
  • Current — operational access is active;
  • Read-only — the appointment ended within the previous seven days and the relevant view explicitly allows grace-period access;
  • Expired — the seven-day grace period has ended;
  • Revoked — the appointment was deactivated or formally revoked.

Read-only access permits safe HTTP methods such as GET but rejects changes. Revocation requires a reason of at least 10 characters in the current interface.

3. Data and privacy architecture

3.1 Reusable voter identity

VoterIdentity belongs to an association and stores protected member details, including staff or membership number, name, email, phone, institution, campus, department, membership category and constituency. Searchable identity values are represented by keyed hashes in database fields. The underlying sensitive values use encrypted fields where implemented.

The reusable voter identity is not itself permission to vote. Each election has a separate ElectionEligibility record.

3.2 Election-specific eligibility

Each eligibility record stores:

  • election;
  • voter identity;
  • eligibility status;
  • eligibility and exclusion reasons;
  • participation marker (has_voted);
  • date of voting, without a precise vote timestamp;
  • credential-issuance markers;
  • verification notes.

Eligibility statuses are:

  • ELIGIBLE;
  • SUSPENDED;
  • EXCLUDED;
  • CHALLENGED.

Only an active voter with ELIGIBLE status and no previous participation marker may vote.

3.3 Anonymous ballot storage

The accepted ballot uses BallotEnvelope and BallotSelection. These records contain the election public ID, receipt digest, integrity values, position public IDs, candidate public IDs or option values. They contain no voter, user, eligibility, staff number, email, phone or voting-ticket foreign key.

During submission, the system atomically:

  1. locks the eligibility record;
  2. rechecks that the voter can vote;
  3. stores the anonymous envelope and selections;
  4. marks the eligibility as having voted;
  5. deletes the active voting ticket.

The participation count and anonymous ballot count must agree before tallying.

3.4 Protected and public files

Protected storage is used for:

  • committee appointment letters;
  • user imports;
  • voter imports;
  • candidate imports;
  • nomination supporting documents;
  • nomination photographs before approval;
  • officer-complaint evidence;
  • uploaded signed result declarations.

Protected files have no public base URL and are served through permission-controlled Django views. Approved candidate photographs are copied to the public candidate record because they must appear on the public final list and ballot.

4. Installation and environment preparation

4.1 Supported runtime

The project declares Python 3.12 or later and Django 6.0. Development uses SQLite automatically. Production uses MySQL automatically.

4.2 Environment selector

APP_ENV controls the database and security mode:

  • APP_ENV=development — SQLite, development defaults and HMAC result signing when no Ed25519 key is supplied;
  • APP_ENV=production — MySQL, required production variables, secure cookies and production cryptographic checks.

Do not use the obsolete DB_ENGINE variable; it is not read by config/settings.py.

4.3 Development setup

py -3.12 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txt
Copy-Item .env.example .env
python manage.py generate_security_keys
python manage.py migrate
python manage.py createsuperuser
python manage.py check
python manage.py runserver

Set APP_ENV=development, a long DJANGO_SECRET_KEY and the generated security keys in .env.

4.4 Production setup

Production requires:

  • APP_ENV=production;
  • DJANGO_DEBUG=false;
  • allowed hosts and trusted HTTPS origins;
  • MySQL credentials;
  • protected media outside the public web root;
  • an independent Fernet data-encryption key;
  • an independent HMAC key;
  • a matching Ed25519 result-signing key pair;
  • HTTPS and secure proxy configuration;
  • a cache shared by all application processes;
  • email and SMS configuration where used;
  • cron or an equivalent scheduler.

Run:

python manage.py check --deploy

The production checks reject a weak secret, missing encryption key, reused HMAC key, invalid result-signing keys, SQLite and an in-process local-memory cache.

5. First platform setup

5.1 Create the technical superuser

Use python manage.py createsuperuser. Keep this account separate from routine election work. It may appoint Platform Administrators through the Control Centre and is the only account allowed into Django Admin.

5.2 Create ordinary authorised users

An ordinary user can be created manually or through CSV/XLSX import.

The manual creation form requests:

  • email address;
  • full name;
  • temporary password and confirmation;
  • active-account flag;
  • require-password-change flag.

The form explicitly removes Django staff and superuser privileges. Imported and reset users are forced to change the temporary password at the next sign-in.

5.3 Appoint Platform Administrators

A Platform Administrator appointment requests:

  • ordinary active user;
  • appointment reference;
  • appointment start;
  • appointment end.

Only one platform appointment record may exist per user. Revocation deactivates the appointment and records the revoking user, time and reason. Reinstitution restores an eligible appointment through the application workflow.

6. Association setup

6.1 Association form fields

Field Required Meaning and operational consequence
Name Yes Full official association name. It generates the slug and appears on pages and reports. Names are unique case-insensitively.
Short name No Recognised abbreviation. When entered, it must also be unique case-insensitively.
Description No Brief public or administrative description.
Primary colour Yes Main branding colour stored as a seven-character colour value.
Secondary colour Yes Complementary branding colour.
Data controller name No Institution or authority deciding the purposes and means of processing personal data.
Data protection contact No Email address for privacy and data-protection enquiries.
Retention days Yes Number of days used by the operational-data purge command for committed import batches and notifications. It is not a universal automatic deletion period for all election evidence.
Active Yes/No Inactive associations remain in the database but should not be used for new live elections.

The Control Centre association form exposes an optional logo and institutional-domain list. Enter domains without @, separated by commas. When the domain list is empty, registered-email verification does not impose an additional domain restriction. Logo uploads are limited to the accepted image formats and size.

6.2 Assign association governance

The current form allows Owner and Administrator assignments to active ordinary users. A user can hold only one membership record for the same association. Staff and superuser accounts cannot be selected. The application protects against deactivating the sole active Owner without a replacement.

7. Election-cycle creation

7.1 Election types

  • Welfare Committee election;
  • Mutual Fund Committee election;
  • Main Executive election;
  • By-election;
  • Runoff election;
  • Confirmatory election;
  • Other election.

For the three ordinary types, the model enforces one of each type per association and year. They must follow Welfare, Mutual Fund and Main Executive order with at least one full calendar month between polling dates. The ordinary Main Executive election must be in December. These scheduling rules should be changed only through an approved governance decision and code revision.

7.2 Election form fields

Field Purpose
Title Public and administrative election name.
Description Scope, purpose or notes visible in relevant interfaces.
Election reference Unique reference within the association, for example SOBAMS-2026-01.
Election type Governing schedule category.
Nomination mode Determines how candidate records originate.
Nominations open / close Required for SELF and MIXED modes; closing must precede voting.
Voting opens / closes Poll schedule. Closing must be later than opening; continuous duration cannot exceed 48 hours.
Required result approvals Minimum distinct approvers. The model requires at least two and publication also requires Commissioner approval.
Email codes Allows delivery/use of election one-time codes by email.
SMS codes Allows delivery/use of election one-time codes by SMS.
Member PIN Allows staff/member number plus PIN verification.
Institutional email Allows registered email plus six-digit verification code.
Assisted verification Enables the authorised assisted-verification workflow; the server rejects the route when disabled or when voting is closed.
WebAuthn Enables passkey registration and authentication endpoints.
Receipt verification Controls whether accepted anonymous ballot receipts for this election can be verified publicly. Disabled and unknown receipts return the same negative result.
Provisional results Reserved compatibility field. It is not exposed as a normal editable setting because a distinct provisional-result lifecycle is not implemented.
Auto-close Permits the scheduled command to close an open poll when its configured close time passes.

7.3 Status lifecycle

The statuses are:

  1. DRAFT;
  2. NOMINATIONS;
  3. READY;
  4. OPEN;
  5. CLOSED;
  6. TALLYING;
  7. AWAITING_APPROVAL;
  8. PUBLISHED;
  9. CANCELLED;
  10. INVALIDATED.

The scheduled command changes DRAFT to NOMINATIONS when the nomination window opens, returns NOMINATIONS to DRAFT when the window closes, and closes an expired OPEN poll when auto-close is enabled. Opening voting is a controlled Commissioner action after readiness passes.

7.4 Correcting, deleting, cancelling and replacing cycles

Election-cycle deletion is deliberately more restrictive than ordinary editing. A cycle may be permanently removed only when it is a verified unused Draft and the supported deletion service confirms that no electoral, voter, governance or audit-dependent record exists. Relevant checks include appointments, nominations, candidates and positions requiring preservation, register certification or use, credentials, ballots, participation markers, tally snapshots, approvals, declarations, incidents, objections and complaints.

The application must repeat the checks immediately before deletion in a transaction. Confirmation should require the election reference and a reason. The deletion audit evidence must survive removal of the cycle row, for example through an independent platform-level event or immutable snapshot.

If the controlled Delete action is not displayed, correct the Draft where possible or use cancellation, invalidation or a separately referenced replacement cycle. Do not delete the record through Django Admin, direct SQL or an ad hoc production shell. Archive and supersede may be governance descriptions rather than model statuses in the current release.

8. Nomination modes

8.1 Commission upload only (UPLOAD)

Use this when candidates are determined through an external or Commission-controlled process. Self-nomination pages are not enabled. Authorised officers may create candidates directly or import them. Nomination dates are not required. The final candidate list still requires approved candidate records, photographs and sufficient candidates for each elective position.

8.2 Self-nomination (SELF)

Use this when every candidacy must originate from an eligible voter's own submission. Nomination dates are compulsory. The public nomination form requires staff/member number, PIN, position, statement and photograph. The Commission reviews each record. Approval creates or updates a linked public Candidate. Direct Commission-entered candidate records are invalid in this mode and must be deleted before publication.

8.3 Self-nomination and upload (MIXED)

Use this when online self-nominations and authorised Commission entries coexist. Nomination dates are compulsory. Approved self-nominations create linked candidates; direct or imported candidates are also valid. Officers must avoid duplicate candidate records and ensure every approved candidate has a photograph.

8.4 No nomination stage (NONE)

Use this where candidate or question content is already authorised before CivitasVote is configured. No public nomination window is used. Officers add candidate records or ballot questions directly. This mode is suitable for runoffs, referenda, confirmatory ballots and elections whose nomination procedure occurs outside the system.

A full comparison is in docs/NOMINATION_MODES.md.

9. Committee appointment and readiness

9.1 Appointment procedure

Association governance creates each appointment through the election detail page. Select any active CivitasVote user; the user does not need to be a voter. Upload the signed PDF letter and enter the reference and dates. The system calculates and stores a SHA-256 hash of the appointment letter.

9.2 Readiness appointment rules

Readiness fails where:

  • a core role is missing;
  • a core role has multiple active holders;
  • the three core roles are not held by three distinct people;
  • an optional single-holder office has multiple active holders;
  • a person serves in both Commission and Appeals roles;
  • an appointee's user account is inactive;
  • reference, letter or dates are missing;
  • the appointment begins after the election process starts;
  • the appointment ends before three days after voting closes.

An Appeals Panel is optional. When no current Appeals Chair or Member exists, officer complaints route to the association appointing authority.

10. Voter directory and election register

10.1 Directory versus register

The association directory is the set of reusable VoterIdentity records. An election register is the set of ElectionEligibility rows for one election. Copying or importing a register never copies ballots, credentials or participation history.

10.2 Register sources

  • Association member directory — copies every active voter identity as ELIGIBLE.
  • Previous election register — copies all prior statuses or eligible-only records.
  • Empty register — creates no entries and allows manual/import population.

Replace existing deletes current draft eligibility rows before copying. It is refused where participation markers exist.

10.3 Manual voter entry

The form includes staff/member number, full name, email, phone, institution, campus/branch, department/unit, membership category, constituency, masked identity hint, active status, election eligibility status and eligibility reason. Staff/member number is unique within an association through a keyed hash.

The masked identity hint must not contain a full national identification number. It is intended for a short masked fragment such as ****1234.

10.4 Import

CSV/XLSX voter import validates first, displays a preview and commits only when no validation errors remain. Existing staff/member numbers update the reusable voter and election eligibility. The exact columns are documented in docs/IMPORT_AND_BULK_UPLOAD_GUIDE.md.

10.5 Eligibility review

Officers may change status, eligibility reason, exclusion reason and verification notes while the register is editable. Every change invalidates an existing register certification.

10.6 Register certification

Only the Commissioner, Secretary or technical superuser may certify. The reference must contain at least five characters. Certification requires at least one active eligible voter and no participation markers. The system stores a keyed digest of the register. Any later voter-level change returns the register to DRAFT and removes the certification metadata.

10.7 Opening and freezing

At opening, the system verifies the certified digest and stores a frozen register snapshot and configuration fingerprint. Before tallying, it compares the current register with the frozen snapshot. A change stops tallying for investigation.

11. Positions, questions and candidates

11.1 Position fields

Field Meaning
Title Office or question shown on the ballot.
Description Voter guidance displayed as help text.
Kind Single choice, multiple choice, Yes/No or referendum.
Seats Number of winners for an elective multiple-seat position.
Maximum selections Highest number of candidates a voter may choose. It cannot be below seats. Single, Yes/No and referendum types require exactly one.
Order Display sequence on the ballot.
Required Whether the form requires a response.
Allow abstain Adds an abstain/leave-blank option and changes required-field behaviour.

11.2 Candidate fields

  • ballot name;
  • biography;
  • manifesto;
  • photograph;
  • ballot order;
  • status;
  • nominee reference.

Candidate statuses are PENDING, APPROVED, REJECTED, WITHDRAWN and DISQUALIFIED. Approved candidates require a valid photograph. Direct candidate creation is blocked in SELF mode.

11.3 Candidate photograph rules

The validator checks the actual image, not only the extension. Permitted formats are JPEG, PNG and WebP. Maximum size is 5 MB. Dimensions must be at least 400 × 400 and no more than 6000 × 6000 pixels.

Candidate import does not include a photograph column. After import, officers must upload photographs individually before approved candidates can be published or pass readiness.

12. Self-nomination and vetting

12.1 Public submission

The election must use SELF or MIXED mode and the current time must be within the nomination window. At least one elective position must exist. The voter supplies:

  • certified-register staff/member number;
  • personal voter PIN;
  • position;
  • statement of 20–3000 characters;
  • required candidate photograph;
  • optional PDF or DOCX supporting document, maximum 5 MB.

The system verifies PIN credentials and current ELIGIBLE status. One voter cannot submit more than one nomination for the same position in the same election.

12.2 Statuses

  • SUBMITTED — received but not yet formally taken under review;
  • UNDER_REVIEW — vetting in progress;
  • APPROVED — valid and linked to an approved Candidate;
  • REJECTED — not admitted; reason of at least 10 characters is required;
  • WITHDRAWN — withdrawn; reason of at least 10 characters is required.

Rejected and withdrawn nominations are completed decisions. They remain in the audit register but do not appear on the final candidate list and do not block publication.

12.3 Candidate synchronisation

On approval, the system requires a protected nomination photograph, creates or updates a Candidate, copies the photograph to public candidate media, sets status APPROVED and links the records. When a linked nomination later becomes rejected or withdrawn, the candidate status changes accordingly.

12.4 Final candidate-list publication

Publication requires:

  • voting has not opened;
  • SELF/MIXED nomination period has closed;
  • no SUBMITTED or UNDER_REVIEW nominations;
  • every approved nomination has a photograph;
  • every approved nomination has a linked approved Candidate;
  • no stale approved Candidate linked to a non-approved nomination;
  • every approved candidate has a photograph;
  • each elective position has at least one approved candidate;
  • a multiple-seat position has at least as many approved candidates as seats;
  • in SELF mode, no candidate lacks a source nomination.

The interface provides individual and bulk deletion of unlinked candidate records in SELF mode. Deletion is available only before voting opens and is audit logged. File deletion occurs after the database transaction commits.

13. Objections and officer complaints

13.1 Election objection

A public user may submit an objection while the election is in NOMINATIONS, READY, OPEN, CLOSED, TALLYING, AWAITING_APPROVAL, PUBLISHED, CANCELLED or INVALIDATED status. Types include candidate eligibility, nomination decision, voter register, voting process, tally result and other electoral matter.

The form records claimant name, optional email, subject, grounds, requested remedy and an optional related candidate. Candidate eligibility objections require a candidate. The claimant's sensitive fields are encrypted; an email hash supports controlled lookup.

Commissioner, Deputy, Secretary, Returning Officer and Registration Officer roles may review the queue. Final RESOLVED or DISMISSED decisions require reasoned text of at least 20 characters.

13.2 Officer complaint

A public user selects an appointed officer and submits complaint type, claimant details, subject, grounds, remedy, recusal request and optional PDF/JPEG/PNG evidence up to 10 MB. The system hashes the evidence.

Complaints against Appeals Panel officers route to the association appointing authority. Other complaints route to an available Appeals Panel; where no current Appeals reviewer exists they fall back to the appointing authority. The accused officer cannot review their own complaint.

Statuses are SUBMITTED, UNDER_REVIEW, REFERRED, RESOLVED and DISMISSED. Referral and final decisions require at least 20 characters of reasons.

14. Readiness and opening voting

14.1 Readiness checks

The current readiness service checks:

  • at least one position or question;
  • at least one active eligible voter;
  • certified voter register and matching digest;
  • no existing participation markers;
  • no anonymous ballots already stored;
  • complete core committee and valid appointments;
  • no Commission/Appeals conflict;
  • approved candidates for elective positions;
  • photographs for approved candidates;
  • sufficient candidates for multiple-seat positions;
  • published final candidate list where elective positions exist.

Readiness does not replace a witnessed mock election, constitutional review, infrastructure check or penetration test.

14.2 Who opens voting

The Commissioner performs the open action. The election must be DRAFT, READY or NOMINATIONS and all readiness errors must be cleared. If the configured start is in the future, manual opening changes the start time to the current time. Opening freezes the register and configuration fingerprint.

15. Voter verification and credentials

15.1 One-time voting code

Officers may issue codes through EMAIL, SMS, PRINT or ASSISTED channels as permitted. Codes are stored only as hashes, are single-use, and expire no later than the election close. PRINT delivery produces a CSV containing member number, voter name, code and expiry; it must be handled as confidential material.

15.2 Member PIN

The voter enters staff/member number and PIN. Five failed PIN attempts lock the portal account for 30 minutes. A successful login clears the failure state. PIN activation uses a registered email verification code and matching staff/member number.

15.3 Institutional email

The voter requests a six-digit code. The system deliberately gives a generic response even where no eligible matching record exists. Codes expire after 10 minutes and permit no more than five failed attempts. Where institutional domains are configured, the supplied email must match one of them.

15.4 Passkey

Where WebAuthn is enabled, the voter may register or use a passkey through the dedicated endpoints. Production configuration requires the relying-party ID and HTTPS origin to match the deployed domain.

15.5 Assisted verification

Polling Officer or Commissioner roles may issue a two-hour assisted code during an open poll after recording a verification note. Assisted personnel must not observe or influence ballot selections.

15.6 Voting ticket

Successful verification creates a 15-minute, one-per-eligibility voting ticket stored as a hash, associated with the current session and fingerprinted with hashed IP and user-agent values. Creating a new ticket replaces the previous one.

16. Ballot completion and receipt

The ballot is built dynamically from positions and approved candidates.

  • Single choice — one candidate or abstain where allowed.
  • Multiple choice — up to maximum_selections approved candidates.
  • Yes/No and referendum — YES, NO and optional ABSTAIN.

The server revalidates every candidate choice. A voter cannot submit an invalid candidate ID or exceed the maximum. Submission is irrevocable in the active workflow. The receipt code is displayed once after submission and stored only as a digest in the ballot envelope.

Receipt verification confirms that a matching accepted envelope exists and that its integrity hash remains valid. It does not reveal selections, voter identity, time or position-level choices.

17. Closing, tallying, approval and publication

17.1 Closing

Only an OPEN election can be manually closed. The configured end time is reduced to the current time where necessary. The scheduler also closes expired polls when auto-close is enabled.

17.2 Tally

The Commissioner generates a tally only after closure. A normal tally cannot be generated where a current tally already exists; a controlled recount must be used. A recount reason must contain at least 10 characters.

Tallying:

  1. verifies the frozen voter register;
  2. verifies each ballot envelope integrity hash;
  3. rejects tallying where integrity failures exist;
  4. reconciles participation count with anonymous ballot count;
  5. counts candidates/options;
  6. identifies winners or ties;
  7. calculates a canonical JSON digest;
  8. signs the digest;
  9. creates a versioned current snapshot;
  10. moves the election to AWAITING_APPROVAL.

17.3 Result signing

Development may use HMAC-SHA256. Production requires Ed25519 and the production check verifies that the public and private keys match. The visible digest and signature values demonstrate system-level integrity metadata; they are not a certificate-backed PDF digital signature.

17.4 Approval

Eligible result approver roles are Commissioner, Deputy, Secretary, Returning Officer and Auditor. An appointment must be current and belong to the election. A rejection returns the election to CLOSED. Publication requires:

  • Commissioner approval; and
  • the configured number of approvals from distinct users, minimum two.

17.5 Public results

Published elections appear on the public results page and previous-results archive. The system supports CSV export, a certified-results PDF, a generated result declaration and an uploaded signed declaration.

17.6 Generated declaration

The generated declaration includes:

  • organisation, election and declaration references;
  • voting period and declaration time;
  • eligible and authenticated voter counts;
  • ballots, valid and rejected totals;
  • declared result table;
  • electronic approval record;
  • incident and recount statement;
  • Returning Officer and Commissioner signature spaces;
  • two representative acknowledgement rows for every approved candidate;
  • result digest and signature value;
  • page footer and reference.

The acknowledgement table expands over additional pages and repeats its heading. Unused representative lines may remain blank.

17.7 Uploaded signed declaration

Authorised Commissioner, Secretary or Returning Officer roles may attach a prepared signed PDF after result publication. The system stores the original filename and SHA-256 hash in protected storage. Public declaration download serves the signed file when available; otherwise it generates the system declaration.

17.8 Ties and runoff

The system marks a tie where the selection boundary is tied. The Commissioner may create a draft runoff from current tied positions. The runoff copies verification settings and eligible voters but requires fresh officer appointments, a new certified register and separate readiness.

18. Cancellation, invalidation and historical retention

Only the currently appointed Electoral Commissioner can perform a formal cancellation or invalidation. From the election dashboard, open Commissioner controls and use the applicable exceptional-action link. The confirmation form requires a formal reason of at least 20 characters and explains the institutional consequences before submission.

The permitted transitions are deliberately different. Cancel election is available from Draft, Nominations open, Ready to open and Voting open. Invalidate election is available from Voting open, Voting closed, Tallying, Awaiting result approval and Results published. Voting open is the only state in which either action can be selected because the legal basis may concern discontinuing the live poll or determining that the process cannot stand. Governance must define which decision is appropriate. A Cancelled or Invalidated election cannot be changed to the other terminal status.

On confirmation, the system locks and rechecks the election record, changes the status, stores the reason, removes any publication timestamp, creates a resolved critical incident and writes a hash-chained audit event containing the previous status, new status and incident identifier. These operations are committed together. A failure prevents a partial exceptional action.

Cancellation means the election will not proceed or continue under the authorised decision. Invalidation means the process or outcome has formally been determined not to stand. Neither action erases the cycle or its evidence. Appointments, voter-register records, ballots, tally snapshots, approvals, incidents, objections, complaints and audit history remain attached to the original cycle.

Where a replacement election is required, create a separate cycle with a new reference and record the relationship and reason. Do not overwrite the original reference or reuse its audit history. The current model does not provide separate Archive or Superseded statuses or a structured replacement-cycle relationship. Treat those terms as institutional record-management descriptions and use approved descriptions, incidents or external registers without manually inventing status values.

19. Audit, notification and retention operations

19.1 Audit ledger

Audit events are scoped, sequenced and hash chained. Each event contains event type, actor UUID where applicable, election public ID, object reference, request ID, hashed IP, metadata, previous hash and event hash.

Verify with:

python manage.py verify_audit_ledger

A failure must be investigated before relying on the audit record.

19.2 Notification outbox

Email and SMS are queued. The dispatcher marks records PENDING, PROCESSING, SENT or FAILED, increments attempts and records provider references or errors. Run every minute:

* * * * * /path/to/venv/bin/python /path/to/project/manage.py dispatch_notifications --limit 100

19.3 Temporary credential purge

*/10 * * * * /path/to/venv/bin/python /path/to/project/manage.py purge_expired_credentials

This removes expired one-time credentials, email codes and voting tickets.

19.4 Retention purge

purge_operational_data is dry-run by default. It reports expired temporary credentials and organisation-specific notifications and committed voter/candidate import batches older than the organisation's retention period. Add --commit only after reviewing the report and backup.

The command does not purge ballots, tally snapshots, audit events, appointment letters, objections, complaints, result declarations or general voter identities.

20. Imports

The three implemented imports are:

  1. ordinary authorised users;
  2. voter directory/election register;
  3. Commission-entered candidates.

All accept CSV or XLSX up to 5 MB, save the source in protected storage, validate into row records, display errors and warnings, and require an explicit commit. Exact schemas and duplicate behaviour are in docs/IMPORT_AND_BULK_UPLOAD_GUIDE.md.

21. Help Centre and System Documentation

The public Help Centre at /help/ is intentionally limited to voter-facing guidance. The System Documentation portal at /help/docs/ contains role-aware operating instructions for authorised administrators and appointed election officers. Both surfaces render only files registered in help_center/registry.py; raw HTML is disabled, paths are constrained to docs/, and audience checks are enforced before a topic is displayed. Registered Markdown under docs/ is therefore runtime content and must not be removed from production while either documentation surface is enabled.

22. Backup, recovery and release discipline

Back up together:

  • MySQL database;
  • public media;
  • protected media;
  • .env and cryptographic keys through a secure secret-management process;
  • deployed source version and dependency lock information;
  • web-server and scheduler configuration.

Restore tests must be performed away from production. Loss of DATA_ENCRYPTION_KEY makes protected encrypted fields unreadable. Loss of the result-signing private key prevents future matching signatures; loss of the public key prevents independent verification of existing Ed25519 signatures. Do not regenerate keys casually on an existing production database.

Before a binding election:

python manage.py makemigrations --check --dry-run
python manage.py check
python manage.py test
python manage.py verify_audit_ledger
python manage.py collectstatic --noinput
python manage.py check --deploy

Also perform load, accessibility, backup-restoration, role-access, mock-election and incident-response tests.

23. Files and directories

Use docs/PROJECT_FILE_CLEANUP.md before committing, transferring or deploying the project. In particular, never place .env, db.sqlite3, media/, protected_media/, staticfiles/, __pycache__/ or compiled Python files in a source archive. Media and databases may contain live evidence and may be removed from a source package but must not be deleted from a live server without an approved retention or recovery process.

24. Known implementation limitations requiring governance or code review

The integrated source audit corrected earlier endpoint, permission, transaction, documentation and packaging inconsistencies. The following limitations remain and must not be hidden:

  1. provisional_results_enabled is retained for compatibility, but the software does not implement a distinct provisional-versus-final publication lifecycle or petition deadline gate.
  2. Candidate spreadsheet import does not import candidate photographs; photographs require a separate controlled upload and validation stage.
  3. The supplied archive contains compiled evidence of historical migration files that are absent from the authored source. Existing production migration history must be reconciled before deployment.
  4. The audit chain and ledger head are stored in the same database. Independent periodic anchoring is recommended for stronger tamper evidence.
  5. Notification delivery is at-least-once; provider idempotency and delivery reconciliation are recommended.
  6. The original authored static/ directory was missing from the archive. Required assets were restored or reconstructed, but visual regression testing remains necessary.
  7. The project does not contain a structured replacement/supersession relationship between an original cycle and a replacement cycle.
  8. Static source review does not substitute for penetration testing, MySQL load testing, accessibility testing, backup restoration or legal and constitutional approval.

Receipt verification, member-PIN access and assisted verification are now enforced by their endpoints. Organisation branding/domain fields are exposed through the intended form, CI uses APP_ENV, and controlled unused-Draft deletion is implemented with blockers, confirmation, transaction locking and audit retention.

25. Support and escalation

Operational staff should preserve the request ID displayed in response headers/logs, election reference, public IDs, time, user role and exact error message. They must not send passwords, PINs, one-time codes, private keys, complete voter registers or ballot screenshots through ordinary support channels.

For routine issues, use docs/TROUBLESHOOTING.md. For a suspected security incident, stop discretionary changes, preserve logs and evidence, notify the Commissioner, ICT/Data Protection officer and appointing authority, and follow the incident and exceptional-action procedure.

Continue the procedure