Mycelium Developer Network: Bootstrap Stage One, Project Change Acceptance
Khleedril, September 2025

Table of Contents

1. Abstract

As it stands, after bootstrap Stage 01, the Mycelium network is useful for appraising an on-line identity as a trusted real person. The next step towards becoming functionally useful as an online governance tool is to allow them to vote on project actions. As the Mycelium project itself is the first application, we present a HTML polling-booth server and adjudicator daemon to operate the first vote on this project, with the intention that it can be adapted to other votes and other projects.

1.1. Audience

This document is aimed at software developers who manage an Internet web server, and are comfortable with HTTPS, JSON, and PGP, and can wrangle and compile Rust applications.

1.2. Distribution

Wide dissemination of this document is strongly encouraged, but modifications are not permitted. The document should be referred to by the title and date shown above. Legally the work should be considered to be copyrighted by the author with terms according to the Creative Commons (CC) BY-ND2 license. The document is being discussed on Mastodon under the hash-tag #myceliumboot1.

1.3. Provenance

The source text for this document and the referenced source code exists as commits in a GIT repository — at this moment in time residing at https://khleedril.org/forge/mycelium/mycelium — signed by khleedril@a.b, PGP fingerprint E23C21ED864FF4F3A7114CDFCA471FD501618A49, the same key that I’m using in the Mycelium network; it will hopefully develop reputation as the network evolves! The full public key is at https://khleedril.org/gpg-key.

If you have access to the Guix command, you can run

guix git authenticate \
       d92072679363b63576862ca206add26f8039114c \
       E23C21ED864FF4F3A7114CDFCA471FD501618A49

to assert the authenticity of the entire repository after you have cloned it to your own machine3, 4.

2. Introduction

The Mycelium network is intended to provide mutual provenance of people, and to provide tools, so that they can participate in on-line governance structures and their procedures. At the moment it is targetted at free software developers who maintain their own web prescence, as it currently requires this level of expertise to participate. It is intended to turn into a general-purpose toolkit which anybody can use, eventually, once correct operations have been worked out and user-friendly frontages have been devised.

So, we want to make a change in the Mycelium project, an addendum which allows people to vote on changes. Here we go again: Catch-22!

The problem with the Mycelium network as it stands (after the Stage-0 bootstrap1) is that it is good for answering a question like, “Is this a real person?” but not a question like, “What is the consensus on this personʼs proposal to make a change in a project?” The reason is that the latter question is an opinion of the whole network, and there is no facility for doing this given that the network is fundamentally not traversible and you essentially get the opinion of the first person who expresses one.

There is also the issue that many measures are weighted by friends’ trust levels in one another, and so the true vote that the voter intended to make will be adjusted by the network, not seen directly; a different answer might be obtained if the information is first solicited from a different friend of the project.

The only way to make this work is for a project to directly poll the end-points of all people who wish to take part in a vote, asking them directly for their opinion. But, as people are not discoverable, it is necessary for them to come forward and register their desire with the project to participate in a vote.

The following is an outline of the proposed scheme.

A vote is arranged by a person (in the case of this particular proposal, Khleedril: E23C21ED864FF4F3A7114CDFCA471FD501618A49) creating a new vote context, UUID, which in this case happens to be 8cc0f310-2ade-4569-b7cb-33c340a05761. People vote by giving a measure to that person against that context, and setting their assessor end-point up to provide this opinion. 50 is neutral, which in a voting context is pointless. Above 50 is a vote in favour, below is a vote against. Normally people should choose either 100 or 0, but refinement of an opinion is possible with intermediate values if the voter so wishes. A more developed project might have a policy which only accepts yea or nay, but that’s down the line.

The project should then provide a web service at which voters can register. It has to be the project that does this as a nefarious vote proposer could give an unrepresentative — forged — result.

This is a HTML page which explains the issue to be resolved and any governance rules which will be used in the polling methodology. The page should give indications of how the voting process is proceeding, perhaps displaying interim results. The site allows people to declare their interest in voting, giving an assessor URI (which SHOULD NOT be the same one they give to their friends, but it SHOULD direct to the same service). When this is given, the system must first inquire of its own friends (the project governors or other trusted group) the person rating of the incumbent (must be above 75), and the assessor rating (which must be above 55). All being well the person’s assessor end-point is retained.

The final reckoning happens by asking all the registered and verified assessors for their score, and then maybe making a weighted average; the weights might be derived from the assessor context, a project context, and/or other measures which might be deemed appropriate. This would all be according to a project’s governance policy, but since we are in the early stages of bootstrapping we don’t have a policy yet, and do not apply weighting to the votes.

To perform the Stage 1 Mycelium bootstrap, we provide an implementation of the logic alongside this document, and implement it at https://khleedril.org/mycelium-vote. People can cast their votes. There is no policy in place yet how the votes will be assessed, and in this case they will actually be ignored as to not make this change will not allow any progress to happen with the development of the Mycelium network. But at least the new proposal will be exercised and people will gain reputation against the Mycelium context.

2.1. Applicability

Unlike the Stage-0 bootstrap, Stage-1 is not supposed to be prescriptive, and shouldnʼt be taken as definitive of how project votes should take place. It should be regarded as an example of how voting may take place, and its use in ratifying the Mycelium project a demonstration of the usefulness and integrity which clever use of the Mycelium network can bring. It is hoped that projects will be able to use the current implementation as a springboard to the development of their own infrastructure (it is also hoped that, in time, this project will provide more adaptable and user-friendly tools to other projects, including ones outside the realm of FOSS developers).

2.2. Risks

The registration page may be publicised globally, and is open to all
This opens the page to denial-of-service (DOS) attacks and other abuse. We mitigate this with the use of Altcha, which reduces the effectiveness of robot networks, and slows down the turn-around of web requests. [As an aside: it was originally thought that the registration would be done via JSON RPC, but the possibility of DOS attacks led us to choose the HTML route which allows several layers of mitigation against trouble to be deployed. It also has the advantage that we can convey useful information to genuine voters, such as pointers to instructions.]
Voters must declare their assessor end-points
These are normally only given to trusted friends, and exposing them to a project breaks the non-discoverability of the network. We prevent the world from seeing these by transport layer security (TLS), but the project might be nefarious and reap the data for ulterior purposes. The solution is for voters to modify their web servers to deliver the service at a different, temporary, URI, which SHOULD be deleted a short time, say two weeks, after the vote has concluded (in case there are issues forcing a late re-count).
The Mycelium network may become inundated, especially under a DOS attack
This is easily mitigated by not processing registration requests straight away, but queuing them for later assessment. The queue can be traversed at a measured rate. We need to take care to not let the queue get out of control. The only downside is that the progress and result of the voting is not done in real time.

3. Technical Details

3.1. Registration

The design of the registration interface revolves around the hypothetical JSON API (which is not implemented) with the request

{
   "public_key": "<your full, ASCII-armoured, self-signed, public PGP key>",
   "end_point": "<your end-point URI, signed with your private PGP key>"
}

and the return taking the form

{
   "status": "<status>",
   "vote": <vote 0-100> | null
}

if successfully ingested into the system (although the status may be displayed as pending and the vote may be shown as null at this time), or else a single string with an error message will be returned, like

"bad-key"

The statuses which can be returned are

“validated”
you have been authenticated as a voter,
“second-hand”
you have been authenticated by asking other voters,
“rejected-non-person”
you have been assessed to have a person rating below 75,
“rejected-non-assessor”
you have been assessed as having an assessor rating below 55,
“pending”
your registration is on hold until some authentication can take place.

The error messages which can be returned are

“ill-formed-message”
the decrypted message could not be parsed as valid JSON,
“bad-key”
your public key failed the self-signed verification check,
“bad-signature”
the end-point could not be verified with your public key.

It is of course possible that a project’s registration URI is only disseminated, by private channels, to designated friends of the project. This is fine if project policy allows this, but in general, voting, and especially elections, should be open to anyone who feels the need to express an opinion on the matter, and not be exclusive to friends of the project which could be manipulated by a cartel of governors.

Then, since the registration end-point would usually be widely advertised, we must defend somewhat against DOS attacks and general abuse. Thus we choose a HTML/HTTPS interface guarded by an Altcha. The information exchange is logically the same as for the hypothetical JSON API described above.

A user registers their intention to vote through a form on a web page. They must supply their full public key, and their assessor end-point URI signed with their private key. The fingerprint will be calculated from the public key, and then the person, identified by this fingerprint, will be assessed against the person and assessor contexts by the project asking its trusted people (governors, for example). Once this is asserted, the voter’s end-point will be accessed directly to get their actual vote. As things progress and voters are authenticated as people on the Mycelium network, their voting end-points can be used to authenticate other voters (we don’t do this in the early stage as it would open the door to nefarious groups creating isolated network rings and infiltrating the system).

But the end-point SHOULD NOT be the person’s general end-point which they share with their friends. In case the project voting point be intercepted or the project itself has been set up by some nefarious group, real voters should create a new but temporary end-point URI which points to the same assessor service.

It is essential that the end-point is in service for the duration of the voting process, if the vote is to count.

To keep appraised of progress with their registration, registrants can repeat the registration process any time and will be informed of the on-going status of their application to register. To withdraw from the vote, the assessor end-point should be set to return "no-basis" when asked for the vote.

3.2. Adjudication Phases

The actual operation of a vote will need to proceed in phases. The main reason for this phasing is the potential for DOS and side-channel attacks, as the polling boothʼs registration is both widely advertised and open to all-comers, and the need to keep the Mycelium network quiet so as not to burden users who should feel safe participating in the system. Thus in the first place registration details must be put into a queue, and then the queue can be processed in slow time. The last thing we want to do is spam our own friends.

3.2.1. Phase I

This is basically just registering people wishing to vote. We should assert their authenticity to a basic degree, checking they have used their private key properly so that we can extract their voting end-point, but then put off full processing to a queue. Nothing about the poll should be divested to the public in this stage, as, with numbers being small, it might leak information about who is registering (an eavesdropper might notice a registration immediately followed by a query on the Mycelium network for information on the voter, for example).

The adjudicator does nothing in this phase, but watches the count of voters, ready to start Phase II once some threshold number of voters is passed.

3.2.2. Phase II

Once ten or so voters have registered and the registration rate has calmed down from an assumed initial onrush, we can start to ask the projectʼs friends to assert the validity of the voters. We can report to the public the number of voters so far in the system, but keep the information highly granular to thwart side-channel attacks as discussed above. We operate a queuing system, and make use of the Mycelium network to a shallow depth to learn about the voters, regulating requests so that the network is not flooded.

The order of operations is, roughly, use project governors with a depth of one to assess the voting weight of registered voters, and failing this try using validated voters. If verification is still not attained then unvalidated voters can be called upon (these will be flagged as ‘second-hand’ verified, and we generally have little trust in them, but count them for now in the hope that they will become fully verified in due course).

Once a point is reached where no further work can be done, the adjudicator sleeps for a couple of hours or so before repeating the process, and then only if enough new voters have registered.

3.2.3. Phase III

The transition from Phase II to III marks the closing of the registration period, and the start of properly ratifying and polling the voters. The transition should probably happen at some predetermined time, advertised to the community, so they have a definite deadline for re-configuring their servers and registering.

Here we deeply verify all the voters, asking the project friends, and, recursively, verified voters to go deep into the Mycelium network for assertions of person/assessor trust. As a last resort we ask other voters for second-hand opinions. The registration page is be turned off at this stage to ensure that the voting process terminates. We can display a progress indicator to the public about how this process is going, and this can be kept relatively fresh. It is still possible for voters to change their mind about their votes at this stage.

The process is very similar to Phase II, except that accesses to the Mycelium network go deeper. Once the point is reached that no further voters can be verified, the phase ends and the system moves automatically to Phase IV.

3.2.4. Phase IV

The vote is closed. We make a single sweep across all confirmed votersʼ end-points to get their final votes. This could be done very quickly with parallelization. The result is announced immediately on completion. We present the results of the fully confirmed voters and the second-hand ones separately, and generally a project will only be interested in those fully confirmed as real people.

4. Realization

This section is intended for a project to set up a coordinated poll. If you are looking to participate in the first poll, you can go directly to the following chapter.

The voting host software is realized in two parts: polling-booth which is a HTTP server furnishing a HTML form allowing for voters to register their voting end-points, and adjudicator which runs as a daemon process and carries out all the business of the vote. The two pieces of software connect through a MariaDB database (which could easily be swapped for Sqlite or Postgresql with some small modifications to the source code; the Rust Diesel crate is used to communicate with the back-end).

This software is absolutely NOT plug-and-go; projects will need to set up their infrastructure, fully review and modify the source code as appropriate ‒ especially the constants at the heads of adjudicator.rs and polling_booth.rs ‒ (the way that voters are qualified and counted will likely be different to the initial projectʼs ways), and modify the HTML web page and all its components to meet the requirements of the project; this page needs to carry an accurate description of the poll being conducted, and any governance rules which are in place to carry out the vote.

A table-space will need to be created in your database, e.g.

echo "create database mycelium" | mysql -

and the diesel migration files should be run on that database, e.g.

cat rust/migrations/*/up.sql | mysql mycelium -

If the project needs to run another vote, either the original table-space will need to be cleared, or else a new table-space must be created and used, the voting software being modified accordingly.

You can now run polling-booth and adjudicator, and, all being well, your vote should be up and running. Go advertise!

5. Participating in the First Vote

This section is intended for an individual to participate in a poll. They are expected to have implemented the Stage-0 bootstrap1, and only need to make small configuration changes to that set-up.

This vote is against person E23C21ED864FF4F3A7114CDFCA471FD501618A49 (the proposer) on context 8cc0f310-2ade-4569-b7cb-33c340a05761; it is a simple 0-100 scale, and votes should generally be 0 (against the proposal) or 100 (for the proposal).

The top of a user’s service source (mycelium.rs), assuming they are using the definitive Rust version, should include

Person { key_fingerprint :
           "E23C21ED864FF4F3A7114CDFCA471FD501618A49",
         measures :
           vec! [("8cc0f310-2ade-4569-b7cb-33c340a05761",
                  <Your vote 0-100>)] }

with the value <Your vote...> set according to your opinion on the matter. Note that this instruction should NOT be applied literally, but the data need to be merged into your existing PEOPLE structure: if you already have an entry in your server for Khleedril, then you MUST add the new measure into the existing measures vector; if either the Person or context entry in measures are repeated, only the first occurrence will have effect (this is a specific detail of how the definitive implementation works).

Once the modified service is compiled and running, you need to modify your web front-end so the service is accessible through a new, hard-to-guess, end-point address.

You then generate your full public key

gpg --armor --export <key ID>

where the key ID may be an associated e-mail address (even if fictitious) or the name. You will post this into the web form at https://khleedril.org/mycelium-vote, including the beginning and ending marker lines.

Then you generate a signed end-point

echo "https://<myhost>.<domain.com>/<my-endpoint-ehauh>"  | \
   gpg --default-key <key ID> --armor --sign -

and copy the output into the second box on the HTML form, again, including the delineating lines.

Note that you could initially be flagged as rejected; please be patient as we need the network to gain some weight so that we can verify, through the network, your authenticity. The second stage of this process, which will kick in when there are enough voters registered, will make some stronger efforts to verify you and enrol you in the vote.

Footnotes:

1

Mycelium Totally Un-Discoverable Developer Network: Bootstrap Stage Zero. https://khleedril.org/mycelium-bootstrap-0

2

Creative Commons license with author attribution and no derivatives. https://creativecommons.org/licenses/by-nd/4.0/