"Vote Free" cartoon

Administrator's Manual

This is the administrator's manual for Votorola 0.1.11. It documents the technical procedures for setting up and administering an electoral office in a community, for the purpose of hosting open, continuous elections.

Office  Register  Elections  Web  Mail
Working Examples  Notes and References

Office

This section concerns the electoral office as a whole. The office consists of server nodes; administrative staff; and communication interfaces to users and external sites.

UML diagram

The server hardware requirements for production deployment are currently unknown. All deployments currently combine the mail server, file server, and Web server into a single, physical electoral server, and this ought to be considered when judging the hardware requirements.4 Also to consider, the beta code (when it is ready) will be far from optimized.

Staffing requirements are currently unknown. Most of the workload will probably bear on authentication of the electoral register. The system is designed to off-load this work onto the electorate, as far as possible. As a rough estimate, running local beta trials might require 20 hours per week of administrative time.

Electoral Server

Initial Set Up of Electoral Server

A Unix server is required. Only Linux has been tested, but most other versions of Unix should be okay.1

  1. Ensure you have Java 6:

    $  java -version
  2. Download Votorola, and unpack it. You get a directory named ‘votorola-version’.

  3. Create a symbolic link to that directory. For example:

    $  ln --sym  votorola-version   installation

    (This will simplify later upgrades.)

  4. Smoke test the installation, by running voqproperties:

    $  java -jar installation/votorola/a/manline/bin/voqproperties
    -- listing properties --
    java.runtime.name=Java(TM) SE Runtime Environment
    sun.boot.library.path=/opt/sun-jdk-1.6.0.03/jre/lib/i386
    java.vm.version=1.6.0_03-b05
      . . .

Upgrade of Electoral Server

  1. Download the new version of Votorola, and unpack it to any directory.

  2. Stop any electoral service daemons that are running. These include the mail responder vomailrd, and the Web interface. (You may need to shut down the whole Web servlet container. Merely undeploying the application may or may not work.)

  3. Unmount any mounted lists and counts.2

  4. Relink to the new installation directory, instead of the old. For example:

    $  ln --sym --force --no-deref  votorola-new-version   installation
  5. Remount any lists and counts that were unmounted, above.

  6. Restart any electoral service daemons that were stopped, above.

Subserver

Each electoral server has one or more subservers. A subserver is identified with a local user account on the server. Under this account, the configuration and data files for a collection of electoral services are stored, and its daemons are run.

UML diagram

Initial Set Up of Subserver

  1. Add a new user account on the electoral server, complete with a home directory, a command line shell, and password-protected access for electoral adminstrators. For example:

    $  useradd --create-home subserver-name
    $  passwd subserver-name

    Begin with a single subserver, for private, off-line testing. Later, when you are satisfied that everything works, you can copy its configuration over to a second subserver, for public, on-line service. (Note that working examples of configuration are provided in the appendix, for both on-line and off-line subservers.)

  2. Login under the new subserver account.

  3. Create a configuration script for the subserver:

    ////                                                                 -*- coding:utf-8; -*-
    // Configuration script for the electoral subserver.
    //
    // This file is located at: /home/subserver-name/votorola/subserver.js.
    //
    
        /** Configures the subserver.
          *
          *     @param subserverCC context of type ElectoralSubserver.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         ElectoralSubserver.ConfigurationContext.html
          */
        function configureSubserver( subserverCC )
        {
            subserverCC.setServerName( 'server.mydomain.dom' );
            subserverCC.setTitle( 'Electoral Subserver (Test)' );
              // typically named after the overall district (town or region, for example)
            subserverCC.setShortTitle( 'Subserver (Test)' );
              // limit to roughly 16 characters
    
         // subserverCC.setRegisterName( 'register-name' );
         //// defaults to 'test-register', which should be OK for the off-line subserver
        }
  4. Test that Votorola's executables are accessible from here. For example:

    $  java -jar installation/votorola/a/manline/bin/voqproperties
    -- listing properties --
    java.runtime.name=Java(TM) SE Runtime Environment
    sun.boot.library.path=/opt/sun-jdk-1.6.0.03/jre/lib/i386
    java.vm.version=1.6.0_03-b05
      . . .
  1. If you use Linux kernel option ‘binfmt_misc’, you can run Votorola's executables in the same way as native ones (without having to type 'java -jar' in front of them). For basic instructions, see the example jar-wrapper script.

    You would have to place Votorola's bin directory on the executable path; for example, by adding this line to ~/.bashrc:

    PATH=$PATH:installation/votorola/a/manline/bin

    You could then run the commands in manline/bin, by simple name. (For brevity's sake, we will assume this in the command line examples that follow.) For example:

    $  voqproperties

    (If you installed the .zip package, instead of the .gz, you may have to set execute permissions on the files, as well.)

  1. Test that Votorola's manual pages are accessible:

    $  man Votorola

    If not, then place Votorola's man directory on the search path. For example, by adding this line to ~/.bashrc:

    MANPATH=$MANPATH:installation/votorola/a/manline/man
  2. Test the logging configuration, with help of volog.

    $  volog

    In a typical Java installation, the default configuration sets the console as the log. Wherever the log is, volog will print test messages to it:

    5-May-2008 2:47:59 PM votorola.a.manline.VOLog main
    INFO: volog is running with arguments []
    5-May-2008 2:47:59 PM votorola.g.logging.LoggerX test
    OFF: testing SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST and ALL...
    5-May-2008 2:47:59 PM votorola.g.logging.LoggerX test
    SEVERE: this is SEVERE
    5-May-2008 2:47:59 PM votorola.g.logging.LoggerX test
    WARNING: this is a WARNING
    5-May-2008 2:47:59 PM votorola.g.logging.LoggerX test
    INFO: this is INFO

    You probably want to increase the level (verbosity) to CONFIG, or higher (especially for the off-line subserver). And you probably want messages logged to a file, rather than the console. See the working examples of configuration, directory /opt/jdk/jre/lib in particular.

Database Server

Initial Set Up of Database Server

  1. Ensure you have the PostgreSQL database management system (DBMS). Version 8.0 or later should be sufficient.

    During installation of PostgreSQL, when using ‘initdb’ to create the database cluster, it is recommended that you give the cluster a null locale (‘C’ or ‘POSIX’). This will ensure that the default encoding for strings is UTF-8 (or ‘UNICODE’, in PostgreSQL terms), as we require.

    $  initdb --locale=POSIX

    Or, if you are installing with Gentoo Linux, you can accomplish this during the ‘emerge --config’ step, by setting LANG to an empty string. This will ensure that emerge calls initdb with --locale=C, instead of the host server's locale.

    $  LANG='' emerge --config =postgresql-version

    Otherwise, although we specify the encoding when we create the database (below) there may be issues with the sorting of indeces.3

  2. Start the DBMS process (postmaster) on the server.

  3. Ensure you are logged in as a DBMS superuser. If root has not been made a superuser, then login as postgres.

    $  su - postgres   # if necessary
  4. Create a DBMS account for the subserver user, under the same user name.

    $ createuser subserver-name

    When prompted, answer no to special permissions (for creating databases, other users, and so forth). These are not needed by the subserver user.

  5. Create a subserver database, with the same name as the subserver.

    $ createdb --owner subserver-name --encoding UNICODE  subserver-name

    UNICODE (UTF-8) is necessary to store the full range of possible user input (characters of all languages, and locales).

Register

This section concerns electoral registers for local offices. (Super-registers for higher district offices, and registers at synchronized sites, are not yet supported.)

Initial Set Up of the Electoral Register

  1. Create a general configuration script for the register.

    ////                                                                 -*- coding:utf-8; -*-
    // Configuration script for the electoral register.
    //
    // Located at /home/subserver-name/votorola/services/register-name/service.js,
    // the same name is referenced by setRegisterName(register-name)
    // in subserver.js.
    //
    
        function serviceType() { return 'votorola.a.register.Register'; }
    
    
        /** Configures the register.
          *
          *     @param registerCC context of type Register.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         register/Register.ConfigurationContext.html
          */
        function configureRegister( registerCC )
        {
            // nothing is needed here, yet
        }
  2. Copy defaults of the specialty configuration scripts, to the same directory.

    $  cp installation/votorola/a/register/trust/trust.js \
       /home/subserver-name/votorola/services/register-name/trust.js
    $  cp installation/votorola/a/register/list.js \
       /home/subserver-name/votorola/services/register-name/list.js

    These scripts will configure the specialized register functions. Do not worry about their content, yet. The defaults will suffice for initial set-up.

  3. Smoke test the register, using the voter command shell.

    $  voter me@domain.dom  register-name  set residence 170 Main Street, M1M 1A1
    Old value:  none
    New value:  170 Main Street, M1M 1A1

Compiling a Voter List

What follows would ordinarilly be scripted (see vox-list, for example), and run as a cron job. But here it is in BASH, command by command:

  1. rSNAPDIR=`vosnap register-name`

    The particular register is identified by its register-name.

    When running vosnap for the first time, you may get a permission error from the file system, as vosnap attempts to create the base directory of the snapshot output store. Help it out by creating the base directory as indicated in the error message, and give it appropriate permissions.

  2. rREADYDIR=`volist ready $rSNAPDIR`
  3. volist mount $rREADYDIR
  4. Tell vocount, vomailrd, etc. to use this list as the latest.

    ln -sfn $rREADYDIR $rSNAPDIR/../_readyList_report

    The soft link _readyList_report is created in the base of the register's snapshot output store (which should be a directory named register-name).

  5. Free up space in your file system and database, by unmounting the old list:

    volist umount $OLD-rREADYDIR

    You may have to hunt for the $OLD-rREADYDIR. It will be the one containing a _mountedList.serial file. Usually there is just one mounted list, but actually any number may be mounted. (We need some kind of 'volist umount all'.)

Trust Network

    - incomplete
    - this section concerns the trust-network, underpinning the electoral register
    

Seeding the Trust Network

  1.             - give the register a real trust script
                - see the example script votorola/services/dev-register/trust.js
                
  2.             - extend primary trust edges [to elected registrars],
                - this goes in register's service.js, inserted into function configureRegister
                
    function configureRegister( registerCC )
    {
        ~ ~ ~
    
      // Somewhat more than 3 destinations, for max trust of 3:
      // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        registerCC.addPrimaryTrust( 'officer-1@domain.dom', 3 );
        registerCC.addPrimaryTrust( 'officer-2@domain.dom', 3 );
        registerCC.addPrimaryTrust( 'officer-3@domain.dom', 3 );
        registerCC.addPrimaryTrust( 'officer-4@domain.dom', 3 );
        registerCC.addPrimaryTrust( 'officer-5@domain.dom', 3 );
    
     // registerCC.setPreRegistrationTrustLevel( 1 ); // default is 0
     //// when the trust network is functional
    
        ~ ~ ~
    }

Elections

This section concerns administrator-defined elections. (Support for voter-defined elections will be added in a future release.)

Initial Set Up of an Election

  1. Create a general configuration script for the election.

    ////                                                                 -*- coding:utf-8; -*-
    // Configuration script for an election.
    //
    // Located at /home/subserver-name/votorola/services/election-name/service.js.
    //
    
        function serviceType() { return 'votorola.a.election.Election'; }
    
    
        /** Configures the election.
          *
          *     @param electionCC context of type Election.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         election/Election.ConfigurationContext.html
          */
        function configureElection( electionCC )
        {
            electionCC.setTitle( 'Election Title' );
        }
  1. If you have not already done so, then create a configuration script for the default electoral district.

    ////                                                                 -*- coding:utf-8; -*-
    // Configuration script for the default electoral district.  Elections that do not
    // specify a district (by electionCC.setDistrictConfigurationPath) are assigned to
    // this default.
    //
    // Located at /home/subserver-name/votorola/district.js.
    //
    
        /** Configures the district.
          *
          *     @param districtCC context of type District.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         election/district/District.ConfigurationContext.html
          */
        function configureDistrict( districtCC )
        {
            districtCC.setTitle( 'Title of the District' );
              // e.g. 'City', 'County', 'Ward 4', 'Riding of Trinity-Spadina'
            districtCC.setShortTitle( 'Short-Title' );
              // limit to roughly 16 characters
        }
  2. Likewise, create a configuration script for the default regional scheme.

    ////                                                                 -*- coding:utf-8; -*-
    // Configuration script for the default regional scheme.  Districts that do not specify
    // a scheme (by districtCC.setSchemeConfigurationPath) are assigned to this default.
    //
    // Located at /home/subserver-name/votorola/regional-scheme.js.
    //
    
        /** Configures the scheme.
          *
          *     @param schemeCC context of type RegionalScheme.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         election/district/RegionalScheme.ConfigurationContext.html
          */
        function configureRegionalScheme( schemeCC )
        {
            schemeCC.setTitle( 'Title of the Regional Scheme' );
              // e.g. 'City-Wide', 'Federal and Provincial Ridings', 'City Wards'
            schemeCC.setShortTitle( 'Short-Title' );
              // limit to roughly 16 characters
        }
  3. If you have not already done so, then create a default eligibility script. An example is provided in the installation files. Simply copy it from the installation files, to the subserver's votorola directory:

    $  cp installation/votorola/a/election/eligibility.js  /home/subserver-name/votorola/

    There is no need to edit it, just yet.

  1. Smoke test the new election.

    $  voter me@domain.dom  election-name  vote myChoice@somewhere.net
    . . .
    You were voting for:     nobody
    You are now voting for:  myChoice@somewhere.net
    
    No trace or other results are available, at this time.  The latest count is
    temporarily inaccessible.

    For a more thorough test, you might use a script like vox-voters to register a batch of test voters, and have them cast votes. Then do a vote tally (see below), and inspect the results.

Tallying the Results of an Election

This is similar to the procedure for compiling a voter list, and some of the tips described there will apply here, too.

The voter list must already be compiled, and still be mounted. What follows would ordinarilly be scripted (see vox-count, for example), and run as a cron job. But here it is in BASH, command by command:

  1. eSNAPDIR=`vosnap service-name`

    The particular election is identified by its service-name.

  2. eREADYDIR=`vocount ready $eSNAPDIR`
  3. vocount mount $eREADYDIR
  4. Tell vomailrd etc. to report these results, as the latest:

    ln -sfn $eREADYDIR $eSNAPDIR/../_readyCount_report

    The soft link _readyCount_report is created in the base of the election's snapshot output store (which should be a directory named service-name).

  5. Free up space in your file system and database, by unmounting the old count:

    vocount umount $OLD-eREADYDIR

    You may have to hunt for the $OLD-eREADYDIR. It will be the one containing a _mountedCount.serial file.

Web

This section concerns the Web-based voter interface.

Initial Set Up of the Web Interface

  1. Ensure you have a Java servlet container. Only Tomcat has been tested, but any standard container should work.

  2. Create a servlet context file with the same name as your subserver. For example:

    $  emacs /etc/tomcat-6/Catalina/server.mydomain.dom/subserver-name.xml

    Inside, it ought to look like this:

    <?xml version='1.0' encoding='US-ASCII'?>
    <Context docBase='installation/votorola/a/web/base' override='true'>
    
        <!-- see http://tomcat.apache.org/tomcat-6.0-doc/config/context.html
                for possible, additional items -->
    
        </Context>
  3. Create a configuration script:

    ////                                                                 -*- coding:utf-8; -*-
    // Configuration script for the Web-based voter interface.
    //
    // This file is located at: /home/subserver-name/votorola/web.js.
    //
    
        /** Configures the Web interface.
          *
          *     @param webCC a context of type VApplication.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         web/VApplication.ConfigurationContext.html
          */
        function configureWeb( webCC )
        {
    
         // webCC.mailTransferService().setServerName( 'smtp.provider.dom' );
         //// for outgoing authentication messages, defaults to the mail server on 'localhost'
    
         // webCC.setStyleSheet( 'http://domain.dom/etc/web.css' ); // optional
        }
    
    
        /** Customizes the initialization of the Web interface.
          *
          *     @param web a Web interface of type VApplication, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         web/VApplication.html
          */
        function initWeb( web )
        {
          // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          // Customizeable page sections.  See the various 'XHTML_' keys defined at
          // http://zelea.com/project/votorola/_/javadoc/index-all.html#_X_
    
         // var pp_a = Packages.votorola.a;
         // web.putCustomXHTML( pp_a.web.WP_Help.XHTML_CONTENT,
         //          _voIncluder.fileToString( 'WP_Help.content.html' ));
        }
  4. Restart the servlet container. The Web interface will be accessible at context path /subserver-name/w/. For example:

    http://server.mydomain.dom:8080/subserver-name/w/

Mail

This section concerns the mail-based voter interface.

Initial Set Up of the Mail Interface

  1. Ensure you have a mail transfer agent (MTA) that is configured to receive mail for your electoral server. Votorola has been tested with qmail, but it should work with any MTA that is supported by TMDA.

  2. Set up an inbox for the mail responder. The default (which you can change in your configuration script, further below) is:

    /home/subserver-name/Maildir

    Messages for all electoral services (service-name@server.mydomain.dom) will be delivered to this inbox.

  3. Create a configuration script for the mail interface:

    ////                                                                 -*- coding:utf-8; -*-
    // Configuration script for the mail-based voter interface.
    //
    // This file is located at: /home/subserver-name/votorola/vomailrd.js.
    //
    
        /** Configures the mail meta-service.
          *
          *     @param metaCC context of type MailMetaService.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         mail/MailMetaService.ConfigurationContext.html
          */
        function configureMailMetaService( metaCC )
        {
         // metaCC.setName( 'meta-service-name' ); // the default is the subserver name
        }
    
    
        /** Configures the mail responder daemon, vomailrd(1).
          *
          *     @param daemonCC context of type VOMailRD.ConfigurationContext, per
          *       http://zelea.com/project/votorola/_/javadoc/votorola/a/
          *         mail/MailResponder.ConfigurationContext.html
          */
        function configureMailRD( daemonCC )
        {
            // daemonCC.transferService().setServerName( 'smtp.provider.dom' );
            //// for outgoing messages, defaults to the mail server on 'localhost'
        }
  4. Smoke test the meta-service from the command-line.

    $  voter subserver-name hello
    hello
  5. Run the responder daemon, vomailrd.

    $  vomailrd &

    (It's running in the background, so use ‘fg’ if you ever need to foreground it.)

  6. Deliver an email message for the meta-service, using vodeliver.

    $  echo 'Return-Path: <me@domain.dom>
    Delivered-To: subserver-name@server.mydomain.dom
    Date: Sun, 14 Oct 2007 12:24:37 -0400
    Content-Language: en-US
    MIME-Version: 1.0
    Content-Type: text/plain; charset=us-ascii
    To: subserver-name@server.mydomain.dom
    From: me@domain.dom
    Subject: this is a test message...
    
    hello there
    
    help me please' | vodeliver

    That should put a message in the inbox. Vomailrd should pick it up, and send a reply to me@domain.dom, within about 20 seconds.

  7. Use your ordinary mail client to send a message to the subserver at the same address, subserver-name@server.mydomain.dom. If your MTA receives the message and delivers it to the subserver inbox, then you should get a reply momentarilly.

  8. Configure the MTA to deliver messages for all electoral services (register and elections) to the subserver inbox. (For qmail, see the /var/qmail/alias directory in the working examples.)

  9. Send a message to the electoral register (register-name@server.mydomain.dom), consisting of the single line:

    help

    You should get a reply momentarilly.

    Maybe test an election, too, by sending a help command to election-name@server.mydomain.dom.

The interface will not support voter-input commands (such as 'vote'), until the authentication layer (below) is in place. If a voter-input command is received, then vomailrd will terminate with an error message.

Challenge-Response Authentication

    - rough draft
    - this section concerns the basic authentication layer of the mail-based voter interface
    
  1. Ensure you have Tagged Message Delivery Agent (TMDA) — any recent version.

  2. Ensure you have Perl 5:

    perl --version
  3.             - basic TMDA
                - not forgetting to gen. a crypt_key
                = test TMDA
                
  4.             = ensure you have libraries needed by tmda-filter-wrapper,
                  by test running it, without arguments
                
  5.             = set up MTA and TMDA for electoral authentication
                    - e.g., by following the example configuration
                - note the CAVEATS in tmda-filter-wrapper(1)
                    - it may need tweaking for your MTA
                

Working Examples

Table 1. Configuration Files and Administrative Scripts from the Reference Electoral Server
Directory Description of Contents
/etc General configuration for the reference electoral server (t.zelea.com), as a whole.
/home/tester Home directory of the off-line, reference subserver ‘tester’. The contents are usually compatible with the latest release of Votorola (this is where the release is tested), but sometimes these files are subsequently modified; so refer to the on-line subserver (below), if in doubt.
/home/v Home directory of the on-line, reference subserver ‘v’. The contents are compatible with the latest release of Votorola (0.1.11). This subserver is on-line at http://t.zelea.com:8080/v/w/.
/opt/jdk/jre/lib Default logging configuration for Java applications. The off-line subserver (tester) overrides this, pointing to its own configuration file (with settings that are more verbose). It is using jar-wrapper to invoke Java, so it simply adds this line to its ~/.bashrc:
export JAR_WRAPPER_OPT = \
  "-Djava.util.logging.config.file=$HOME/.java/logging.properties"

The Web interface has it own logging.properties, under /etc/tomcat-6.

/usr/local/bin Scripts vox-* are for electoral purposes.
/var/qmail/alias Mail delivery control (.qmail) files, for delivering incoming mail for electoral services (having specially tagged addresses) to the appropriate subserver.

Notes and References

1.

It would require modification to work under Windows. Unix assumptions are embedded in the code, and throughout this manual.

2.

Mounted lists and counts must be unmounted prior to upgrading, otherwise they may become inaccessible (throwing exceptions ‘java.io.InvalidClassException ... serialVersionUID’) owing to structural changes in database tables, files or code. If this happens, you might have to downgrade in order to unmount them. (Or manually drop the tables, and delete the files.)

3.

Issues are unlikely at the moment, because we do not rely on sorting of query results. See Locale Support. Section 20.1. PostgreSQL 8.0.15 Documentation.

4.

The design allows deployment to be split across multiple physical servers (mail, file, Web, etc.), but the current implementation might require code changes to support this.

maintainer Michael Allan

Copyright 2007-2008, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.