<p>It's Java 21 + Spring Boot + Kubernetes + PostgreSQL + Angular + Electron + ActiveMQ + .NET. It takes a team of dozens and months to set up.</p>
<divclass="think-box">We reimplemented the core cryptographic protocol -- the <em>mathematical heart</em> of this system -- as a single Go binary. Same algorithms, same proof structures, same security properties. Just... simpler.</div>
`
},
{
part: 'Part I: The Project',
title: 'Our Go Reimplementation',
html: `
<divclass="stat-grid">
<divclass="stat-box"><divclass="stat-num">6,565</div><divclass="stat-label">Lines of Go</div></div>
<divclass="lesson-box">You don't need 500K lines to implement a complex protocol. The cryptographic core here is only a few thousand lines —<em>the right</em> few thousand. Knowing what to leave out is as important as knowing what to put in.</div>
<p>This could have been written in Rust, Python, or C. Here's why Go was the right choice for <em>this</em> project:</p>
<divstyle="margin:12px 0;">
<h3style="color:#0969da;">Fits like a glove</h3>
<ul>
<li><spanclass="em">math/big</span> -- arbitrary-precision integers in the standard library (no external bignum dependency)</li>
<li><spanclass="em">crypto/rand</span> -- cryptographically secure random bytes, built in</li>
<li><spanclass="em">Single binary</span> -- <code>go build</code> produces one file, no runtime needed</li>
<li><spanclass="em">Fast compilation</span> -- change code, rebuild, test in under 2 seconds</li>
<li><spanclass="em">Value semantics</span> -- structs are copied by default, which is great for immutable math types</li>
</ul>
</div>
<divstyle="margin:12px 0;">
<h3style="color:#cf222e;">Wouldn't choose Go for</h3>
<ul>
<li>High-performance production crypto (Rust or C would be faster for 3072-bit operations)</li>
<li>Generic math libraries (Go generics are still young)</li>
</ul>
</div>
<divclass="lesson-box">Pick the language that fits the <em>task</em>, not the one you know best. For a PoC that needs big integers, fast iteration, and a clean binary, Go is ideal.</div>
<spanclass="file"> go.mod</span><spanclass="dim">-- 2 direct dependencies</span></div>
<divclass="lesson-box"><strong>cmd/</strong> is <em>thin</em>. It parses flags and calls into <strong>pkg/</strong>. All business logic lives in <strong>pkg/</strong>. This means your library code is reusable and testable without the CLI. The demo.go file is 25 lines -- it parses two flags and calls one function.</div>
`
},
{
part: 'Part II: Structure',
title: 'The Dependency Graph',
html: `
<p>Packages form a clean <spanclass="em">directed acyclic graph</span>. Lower layers know nothing about higher layers.</p>
<spanclass="dim">Layer 1:</span><spanclass="dir">math/big</span><spanclass="dir">crypto/rand</span><spanclass="dim">-- Go standard library</span></div>
<divclass="insight-box"><strong>No circular imports.</strong> Go enforces this at compile time -- you literally cannot create a cycle. This forces you to think about your dependency direction upfront. If package A imports B, B can never import A. This is a feature, not a limitation.</div>
<divclass="think-box">Look at the graph. The <code>math</code> package knows nothing about elections, votes, or shuffles. It's pure math. The <code>elgamal</code> package knows about encryption but not about voters. Only <code>protocol</code> at the top ties everything together. Each layer has a <em>single concern</em>.</div>
<p>That's the entire Go dependency list. The protocol crypto -- ElGamal, zero-knowledge proofs, the Bayer-Groth shuffle, Pedersen commitments -- is implemented from scratch. The one deliberate exception is <em>transport</em> security: the multi-party mode links a small Rust crate (<code>ed25519-dalek</code>, <code>x25519-dalek</code>) for signatures and key exchange.</p>
<divclass="lesson-box"><strong>Own your core domain; borrow the rest.</strong> The election protocol is the core domain, so it's built from primitives -- you understand every line. But hand-rolling Ed25519 or X25519 would be reckless: constant-time, audited implementations are exactly what you <em>should</em> depend on. Knowing which is which is the skill.</div>
value *<spanclass="tp">big.Int</span><spanclass="cmt">// private! cannot be accessed outside the package</span>
group *<spanclass="tp">GqGroup</span><spanclass="cmt">// which mathematical group this belongs to</span>
}</div>
<p>Every field is <spanclass="em">unexported</span> (lowercase). Nobody outside the package can touch the internals. And every operation returns a <em>new</em> element:</p>
<divclass="code"><spanclass="kw">func</span> (e <spanclass="tp">GqElement</span>) <spanclass="fn">Multiply</span>(other <spanclass="tp">GqElement</span>) <spanclass="tp">GqElement</span> {
e.<spanclass="fn">checkSameGroup</span>(other)
result := <spanclass="kw">new</span>(<spanclass="tp">big.Int</span>).<spanclass="fn">Mul</span>(e.value, other.value)
<spanclass="kw">return</span><spanclass="tp">GqElement</span>{value: result, group: e.group} <spanclass="cmt">// NEW instance</span>
}
<spanclass="kw">func</span> (e <spanclass="tp">GqElement</span>) <spanclass="fn">Exponentiate</span>(exp <spanclass="tp">ZqElement</span>) <spanclass="tp">GqElement</span> {
result := <spanclass="kw">new</span>(<spanclass="tp">big.Int</span>).<spanclass="fn">Exp</span>(e.value, exp.value, e.group.p)
<spanclass="kw">return</span><spanclass="tp">GqElement</span>{value: result, group: e.group} <spanclass="cmt">// NEW instance</span>
}</div>
<divclass="lesson-box"><strong>Never mutate. Always return new.</strong> This is the single most important pattern in this codebase. When <code>a.Multiply(b)</code> is called, <code>a</code> doesn't change. <code>b</code> doesn't change. You get a fresh result. This eliminates an entire class of bugs: accidental aliasing, shared mutable state, spooky action at a distance.</div>
`
},
{
part: 'Part III: Types',
title: 'Why Immutability Matters Here',
html: `
<p>Here's a bug that immutability prevents. Imagine <code>big.Int</code> was used directly:</p>
<divclass="code"><spanclass="cmt">// DANGEROUS: what the code would look like without immutability</span>
<spanclass="cmt">// Later, someone "temporarily" modifies the secret key...</span>
temp := secretKey <spanclass="cmt">// This is a POINTER COPY, not a value copy!</span>
temp.<spanclass="fn">Add</span>(temp, big.NewInt(<spanclass="num">1</span>)) <spanclass="cmt">// Oops: this ALSO modifies secretKey!</span>
<spanclass="cmt">// Now secretKey is 43, not 42. The election is broken.</span>
<spanclass="cmt">// And the bug is 50 lines away from where the damage shows up.</span></div>
<divclass="mistake-box">In Go, <code>*big.Int</code> is a pointer type. Assigning it copies the pointer, not the value. Most <code>big.Int</code> operations mutate the receiver. This means that if you pass a <code>*big.Int</code> around, anyone can silently change it. In a cryptographic system, this is catastrophic.</div>
<p>Our <code>GqElement</code> wraps it safely:</p>
<spanclass="kw">func</span> (e <spanclass="tp">GqElement</span>) <spanclass="fn">Value</span>() *<spanclass="tp">big.Int</span> {
<spanclass="kw">return</span><spanclass="kw">new</span>(<spanclass="tp">big.Int</span>).<spanclass="fn">Set</span>(e.value) <spanclass="cmt">// returns a COPY, not the original</span>
}
<spanclass="kw">func</span><spanclass="fn">NewGqElement</span>(value *<spanclass="tp">big.Int</span>, group *<spanclass="tp">GqGroup</span>) (<spanclass="tp">GqElement</span>, <spanclass="kw">error</span>) {
<spanclass="cmt">// ^^^ defensive copy on the way IN</span>
}</div>
<divclass="insight-box">Defensive copies on the way <em>in</em> (constructor) and on the way <em>out</em> (Value()). The internal state can never be mutated by external code. This is a foundational pattern for any code handling sensitive data.</div>
`
},
{
part: 'Part III: Types',
title: 'Compile-Time Safety with Distinct Types',
html: `
<p>We have two kinds of numbers: group elements (G<sub>q</sub>) and exponents (Z<sub>q</sub>). They're both <code>*big.Int</code> underneath, but they're <em>different types</em>:</p>
<divclass="code"><spanclass="kw">type</span><spanclass="tp">GqElement</span><spanclass="kw">struct</span> { value *<spanclass="tp">big.Int</span>; group *<spanclass="tp">GqGroup</span> } <spanclass="cmt">// group elements</span>
<spanclass="kw">type</span><spanclass="tp">ZqElement</span><spanclass="kw">struct</span> { value *<spanclass="tp">big.Int</span>; group *<spanclass="tp">ZqGroup</span> } <spanclass="cmt">// exponents</span></div>
<p>Now look at what happens if you confuse them:</p>
<divclass="code"><spanclass="kw">func</span> (e <spanclass="tp">GqElement</span>) <spanclass="fn">Exponentiate</span>(exp <spanclass="tp">ZqElement</span>) <spanclass="tp">GqElement</span>
<spanclass="cmt">// This compiles:</span>
result := element.<spanclass="fn">Exponentiate</span>(exponent) <spanclass="cmt">// GqElement ^ ZqElement -> GqElement</span>
<spanclass="cmt">// This does NOT compile:</span>
result := element.<spanclass="fn">Exponentiate</span>(otherElement) <spanclass="cmt">// GqElement ^ GqElement -> COMPILE ERROR</span>
<spanclass="cmt">// You can't accidentally pass a group element where an exponent is expected.</span></div>
<divclass="lesson-box"><strong>Use distinct types for distinct concepts.</strong> Even if they have the same underlying representation, wrapping them in separate types lets the compiler catch category errors. A group element is not an exponent. A public key is not a private key. Making the compiler enforce this turns runtime bugs into compile-time errors -- which is always cheaper.</div>
`
},
{
part: 'Part III: Types',
title: 'Runtime Guards: checkSameGroup',
html: `
<p>The compiler can't check <em>everything</em>. Two <code>GqElement</code> values could belong to different groups (different primes). This is a runtime check:</p>
<divclass="code"><spanclass="kw">func</span> (e <spanclass="tp">GqElement</span>) <spanclass="fn">checkSameGroup</span>(other <spanclass="tp">GqElement</span>) {
<spanclass="kw">panic</span>(<spanclass="str">"elements must be from the same group"</span>)
}
}
<spanclass="cmt">// Called at the start of every cross-element operation:</span>
<spanclass="kw">func</span> (e <spanclass="tp">GqElement</span>) <spanclass="fn">Multiply</span>(other <spanclass="tp">GqElement</span>) <spanclass="tp">GqElement</span> {
e.<spanclass="fn">checkSameGroup</span>(other) <spanclass="cmt">// panics immediately if groups don't match</span>
<spanclass="cmt">// ...</span>
}</div>
<divclass="think-box"><strong>Why panic instead of returning an error?</strong> Because mixing groups is a <em>programming error</em>, not a data error. It means the developer wrote incorrect code, not that the user provided bad input. Panicking gives you an immediate stack trace pointing to exactly where the bug is. Returning an error would just propagate confusion. <br><br>This is a deliberate design choice: <strong>validate at construction, panic on invariant violations, return errors for external input.</strong></div>
`
},
{
part: 'Part III: Types',
title: 'Domain Types Tell the Story',
html: `
<p>Look at the top-level domain types. Even without understanding cryptography, you can read what this system does:</p>
<divclass="lesson-box"><strong>Types are documentation.</strong> A developer reading <code>ElectionEvent</code> immediately understands the system has control components, an electoral board, voting cards, a ballot box, shuffle results, and a final tally. The type names <em>are</em> the glossary. If your types read like a story, your code is self-documenting.</div>
<p>That's it. 25 lines. The CLI's job is to parse flags and call a function. The function lives in <code>pkg/protocol</code> where it can be tested, reused, and imported by other tools.</p>
<divclass="analogy-box">Think of <code>cmd/</code> as the steering wheel and pedals of a car. The engine is in <code>pkg/</code>. If you want to build a different car (a web API, a test harness, a GUI), you swap the steering wheel, not the engine.</div>
`
},
{
part: 'Part IV: Patterns',
title: 'Pattern 2: Constructor Validation',
html: `
<p>There are two ways to create a group element. The <em>safe</em> way and the <em>fast</em> way:</p>
<divclass="code"><spanclass="cmt">// SAFE: validates group membership. For external input.</span>
<spanclass="kw">func</span><spanclass="fn">NewGqElement</span>(value *<spanclass="tp">big.Int</span>, group *<spanclass="tp">GqGroup</span>) (<spanclass="tp">GqElement</span>, <spanclass="kw">error</span>) {
<spanclass="kw">return</span><spanclass="tp">GqElement</span>{}, fmt.<spanclass="fn">Errorf</span>(<spanclass="str">"value %v is not a member of the group"</span>, value)
<p>Notice: the unsafe version is <spanclass="em">unexported</span> (lowercase <code>gqElementUnchecked</code>). Only code <em>inside the math package</em> can use it.</p>
<divclass="lesson-box"><strong>Validate at the boundary, trust inside.</strong> The public constructor checks group membership (expensive but safe). Internal operations that are mathematically guaranteed to produce valid elements skip the check. This gives you both safety <em>and</em> performance. The unexported name prevents misuse from outside the package.</div>
`
},
{
part: 'Part IV: Patterns',
title: 'Pattern 3: Composition over Inheritance',
html: `
<p>Go doesn't have inheritance. Instead, we build complex types by <em>composing</em> simpler ones:</p>
<divclass="code"><spanclass="cmt">// Level 1: A single group element</span>
<spanclass="kw">type</span><spanclass="tp">GqElement</span><spanclass="kw">struct</span> { value *<spanclass="tp">big.Int</span>; group *<spanclass="tp">GqGroup</span> }
<spanclass="cmt">// Level 2: A vector of elements (built from GqElement)</span>
<spanclass="kw">type</span><spanclass="tp">GqVector</span><spanclass="kw">struct</span> { elements []<spanclass="tp">GqElement</span>; group *<spanclass="tp">GqGroup</span> }
<spanclass="cmt">// Level 3: A ciphertext (built from GqElement + GqVector)</span>
<divclass="insight-box">Each level is built from the level below. <code>GqElement</code>→<code>GqVector</code>→<code>Ciphertext</code>→<code>BallotBox</code>→<code>ElectionEvent</code>. No inheritance hierarchies, no abstract classes, no "implements" keywords. Just small types composed into larger ones. This is how Go wants you to build software.</div>
`
},
{
part: 'Part IV: Patterns',
title: 'Pattern 4: Interface Segregation',
html: `
<p>The codebase defines one key interface: <code>Hashable</code>. It's tiny:</p>
<divclass="lesson-box"><strong>Small interfaces, concrete types.</strong> Go's philosophy: interfaces should have 1-3 methods. <code>Hashable</code> has 2 methods and is the <em>only</em> interface in the entire codebase. Everything else is concrete types with methods. This keeps the code grounded and easy to follow. You always know exactly which type you're dealing with.</div>
`
},
{
part: 'Part IV: Patterns',
title: 'Pattern 5: Functions That Read Like Specifications',
html: `
<p>Compare the ElGamal encryption <em>specification</em> to the <em>code</em>:</p>
e := <spanclass="fn">schnorrChallenge</span>(group, y, c, ...)
z := b.<spanclass="fn">Add</span>(e.<spanclass="fn">Multiply</span>(x))</div>
</div>
</div>
<divclass="lesson-box"><strong>Good code mirrors the specification.</strong> When a reviewer (or auditor) reads the code, they should be able to hold the spec in one hand and the code in the other and verify them line-by-line. This is not an accident -- it's the result of designing your types and method names to match the domain vocabulary. <code>g.Exponentiate(r)</code> reads exactly like "g to the power of r".</div>
`
},
{
part: 'Part IV: Patterns',
title: 'Pattern 6: Variadic Functions for Flexibility',
html: `
<p>Several functions use Go's <code>...</code> syntax for optional parameters:</p>
<divclass="insight-box">Variadic parameters give you a clean API without overloading (which Go doesn't have) or wrapping things in slices at every call site. Use them when the "extra" parameters are genuinely optional, not when you're too lazy to define a proper config struct.</div>
<spanclass="kw">return</span><spanclass="tp">GqElement</span>{}, fmt.<spanclass="fn">Errorf</span>(<spanclass="str">"value is not a group member"</span>)
}
<spanclass="cmt">// ...</span>
}</div>
<pclass="note">Used when the caller provided data that might be invalid. Let them handle it.</p>
</div>
<divstyle="margin:16px 0;">
<h3style="color:#cf222e;">2. Panic -- for programming errors</h3>
<divclass="code"><spanclass="kw">func</span> (e <spanclass="tp">GqElement</span>) <spanclass="fn">Multiply</span>(other <spanclass="tp">GqElement</span>) <spanclass="tp">GqElement</span> {
e.<spanclass="fn">checkSameGroup</span>(other) <spanclass="cmt">// panics if groups don't match</span>
<spanclass="kw">if</span><spanclass="fn">len</span>(keys) == <spanclass="num">0</span> { <spanclass="kw">panic</span>(<spanclass="str">"must provide at least one key"</span>) }
<spanclass="cmt">// ...</span>
}</div>
<pclass="note">Used when the invariant is the caller's responsibility. This is a bug, not a data problem.</p>
</div>
<divstyle="margin:16px 0;">
<h3style="color:#c2410c;">3. Panic with message -- for "should never happen" in PoC</h3>
<divclass="code">group, err := emath.<spanclass="fn">NewGqGroup</span>(p, q, g)
<spanclass="kw">panic</span>(<spanclass="str">"failed to create group: "</span> + err.<spanclass="fn">Error</span>())
}</div>
<pclass="note">In a PoC, crashing with a clear message is better than littering the code with error propagation for impossible cases. In production, this would be a proper error return.</p>
</div>
`
},
{
part: 'Part V: Error Handling',
title: 'The PoC vs. Production Tradeoff',
html: `
<divclass="think-box"><strong>Should this PoC have better error handling?</strong><br><br>
The single-process <code>demo</code> runs an in-memory ceremony with no untrusted input after the flags are parsed. If something goes wrong there, it's because the <em>math is wrong</em> -- crashing with a stack trace is the right response.<br><br>
But the multi-party <code>netdemo</code> (Part VI½) crosses a real trust boundary: parties exchange signed messages, and a malformed message from a peer must produce a clean rejection, not a panic. So the transport-facing code returns errors and validates every decoded value -- the same code, held to a stricter standard <em>because its inputs are no longer trusted</em>.</div>
<divclass="lesson-box"><strong>Match your error strategy to your context.</strong> Panic on impossible internal states in throwaway code; return errors at trust boundaries where inputs are attacker-controlled. The <em>same</em> project can need both -- what changes is whether the input is trusted.</div>
<divclass="insight-box">Each layer adds meaning. Layer 1 knows about big numbers. Layer 2 knows about groups. Layer 3 knows about encryption. Layer 5 knows about elections. A change to the group math never touches the election logic, and vice versa. This is <em>separation of concerns</em> in practice.</div>
`
},
{
part: 'Part VI: Architecture',
title: 'Tracing a Vote: The Verifiable Shuffle',
html: `
<p>The most complex operation -- the mix-net shuffle -- is orchestrated by a single clean function:</p>
<divclass="lesson-box"><strong>Complex operations should have simple interfaces.</strong> The shuffle involves permutations, re-encryption, commitment schemes, and a 5-sub-argument zero-knowledge proof. But from the outside, it's one function call: input ciphertexts in, shuffled ciphertexts + proof out. All the complexity is <em>behind</em> the interface, not <em>in</em> it.</div>
`
},
{
part: 'Part VI: Architecture',
title: 'Where the Complexity Lives',
html: `
<p>Lines of code by package tell an interesting story:</p>
<spanclass="dim">everything else 515 LOC ########## (8%)</span></div>
<p>Nearly <spanclass="em">30%</span> of the code is the Bayer-Groth shuffle proof. That's the hardest algorithm in the system, so it makes sense that it's the largest package. The orchestration layer (<code>protocol</code>) is only 13%.</p>
<divclass="think-box"><strong>A healthy codebase has its complexity where the problem is complex.</strong> If your orchestration layer is 50% of the code, something is wrong -- the hard parts should be in the specialized packages. If your "utils" package is 30%, you probably have an abstraction missing. The distribution of lines tells you whether your architecture matches your problem.</div>
<divclass="part-sub">The real system isn't one program.<br>It's ten mutually distrusting parties on separate machines.</div>
</div>
`
},
{
part: 'Part VI½: Going Multi-Party',
title: 'The Trust Structure Was Missing',
html: `
<p>The single-process <code>demo</code> is faithful to the <em>protocol</em> but not to the <em>trust model</em>. Every party -- the setup component, four control components, the electoral board, the voting server, the voters, the verifier -- lived as fields on one shared struct. Anyone could read anyone's secret key.</p>
<p>The <code>netdemo</code> mode splits them into separate endpoints (<code>pkg/party</code>). Each holds only its own private state; everything that crosses between parties travels as an authenticated message over a bus (<code>pkg/transport</code>).</p>
<divclass="insight-box">A protocol demo can collapse all parties into one process. A <em>trust</em> demo can't -- the whole point is that no single party sees the whole picture. Splitting them turns "trust us" into "verify every message."</div>
`
},
{
part: 'Part VI½: Going Multi-Party',
title: 'Transport Security -- in Rust',
html: `
<p>Every inter-party message is Ed25519-signed; confidential deliveries (voting cards) use X25519 ECDH + AES-GCM. Crucially, <strong>that cryptography is implemented in Rust</strong>, not Go, and called over a C ABI via cgo:</p>
<divclass="code"><spanclass="cmt">// rust/transportsec (ed25519-dalek, x25519-dalek) -> C ABI -> Go</span>
<p>No RSA anywhere -- including the X.509 certificate authority, whose Ed25519 signatures are produced through a Go <code>crypto.Signer</code> shim that forwards to Rust. A cross-language test proves the Rust signatures are standard RFC 8032 (Go's stdlib verifies them and vice-versa).</p>
<divclass="lesson-box"><strong>Language boundaries are an architecture tool.</strong> Isolating all the signature/key-exchange code in one small Rust crate with a five-function C ABI means the security-critical primitives live in one memory-safe, audited place -- and the Go side literally cannot re-implement or bypass them.</div>
`
},
{
part: 'Part VI½: Going Multi-Party',
title: 'The Validation Boundary',
html: `
<p>Once messages arrive from other parties, they're untrusted. The single serialization layer (<code>pkg/party/wire.go</code>) is the choke point: crypto objects travel as decimal strings and every decode routes through the checked constructors.</p>
<divclass="code"><spanclass="kw">func</span><spanclass="fn">strToGq</span>(s <spanclass="tp">string</span>, group *<spanclass="tp">emath.GqGroup</span>) (<spanclass="tp">emath.GqElement</span>, <spanclass="tp">error</span>) {
v, ok := <spanclass="kw">new</span>(<spanclass="tp">big.Int</span>).<spanclass="fn">SetString</span>(s, <spanclass="num">10</span>)
<spanclass="kw">return</span> emath.<spanclass="fn">NewGqElement</span>(v, group) <spanclass="cmt">// validates membership in G_q</span>
}</div>
<p>A peer cannot inject a value outside the group -- the small-subgroup and non-residue attacks are closed at the exact point where a proof or ciphertext crosses the boundary.</p>
<divclass="insight-box">In a monolith, "is this a valid group element?" is an invariant you establish once. Across a trust boundary, it's a question you must re-ask on every single decode. The architecture makes that unavoidable by funneling all decoding through one validated layer.</div>
`
},
{
part: 'Part VI½: Going Multi-Party',
title: 'Cast-as-Intended, For Real',
html: `
<p>The return codes a voter checks against their card are now computed by the control components <em>from the submitted ciphertext</em> -- not looked up. The voter sends a second ciphertext E2 and a <strong>plaintext-equality proof</strong> that E2 and the ballot encrypt the same vote.</p>
<spanclass="hl">server</span> --> verify proof on every CC, then:
exponentiate E2 by each CC's return-code key,
joint-decrypt --> vote^Σk --> look up short code
<spanclass="dir">voter</span><-- return code -- check against card</div>
<p>If malware encrypts option A for the tally but option B in the return-code channel, the equality proof fails and the ballot is rejected. A unit test drives exactly that attack and confirms it's caught.</p>
<divclass="lesson-box"><strong>Soundness is a property of the whole pipeline, not one function.</strong> The proof, the CC computation, the mapping lookup, and the voter's check only add up to "cast-as-intended" when every link holds -- which is why it needs a test that attacks the seam between them.</div>
<spanclass="dim">A proof-of-concept reimplementation of the Swiss Post
e-voting cryptographic protocol in Go.
Available Commands:
demo Run a full election ceremony end-to-end
present Run an interactive step-by-step presentation
serve Serve the web presentations on the local network
help Help about any command</span></div>
<divclass="lesson-box"><strong>One file per subcommand.</strong><code>demo.go</code> defines <code>demoCmd</code>. <code>serve.go</code> defines <code>serveCmd</code>. <code>presentation.go</code> defines <code>presentCmd</code>. Each registers itself in its own <code>init()</code>. This means adding a new command is: create a file, define the command, done. No editing <code>main.go</code>.</div>
`
},
{
part: 'Part VII: Product',
title: 'The Presentation Mode: Code as Communication',
html: `
<p>The <code>evote present</code> command is 772 lines -- the second-largest file. It doesn't implement any new algorithm. It presents the existing algorithms <em>theatrically</em>.</p>
<divclass="code"><spanclass="cmt">// Helper functions for presentation output:</span>
<spanclass="kw">func</span><spanclass="fn">banner</span>(role, text <spanclass="tp">string</span>) <spanclass="cmt">// "===[ CC0 OPERATOR (BERN) ]==="</span>
<spanclass="kw">func</span><spanclass="fn">showValue</span>(label, val <spanclass="tp">string</span>) <spanclass="cmt">// " Secret key [0]: 4902980..."</span>
<spanclass="cmt">// The presentation calls the SAME crypto functions as the demo,</span>
<spanclass="cmt">// but wraps each step in narration and formatting.</span></div>
<divclass="analogy-box"><strong>Think about your users.</strong> The <code>demo</code> command is for developers verifying correctness. The <code>present</code> command is for teaching the protocol to an audience. Same algorithm, different interface. The best tools have multiple "faces" for different audiences -- and you don't need a GUI framework to build them.</div>
`
},
{
part: 'Part VII: Product',
title: 'What Makes This a Good PoC',
html: `
<divstyle="margin:12px 0;">
<h3style="color:#1a7f37;">What it does well</h3>
<ul>
<li><spanclass="em">Runs end-to-end</span> -- not just key generation, but a complete election</li>
<li><spanclass="em">Verifies itself</span> -- the demo checks every proof, catches its own bugs</li>
<li><spanclass="em">Is readable</span> -- code mirrors the specification line-by-line</li>
<li><spanclass="em">Is self-contained</span> -- one binary, two dependencies, <code>go build && ./evote demo</code></li>
<li><spanclass="em">Has a teaching mode</span> -- the <code>present</code> command explains what it does</li>
</ul>
</div>
<divstyle="margin:12px 0;">
<h3style="color:#cf222e;">What it intentionally skips</h3>
<ul>
<li><spanclass="em">Networking</span> -- everything is in-process (no HTTP, no gRPC)</li>
<li><spanclass="em">Persistence</span> -- all in memory (no database, no files)</li>
<li><spanclass="em">Concurrency</span> -- single-threaded (no goroutines, no channels)</li>
<li><spanclass="em">Comprehensive tests</span> -- the demo <em>is</em> the integration test</li>
</ul>
</div>
<divclass="lesson-box"><strong>A PoC is not a product. Know the difference.</strong> A PoC proves the concept works. It answers: "Can this be done?" A product answers: "Can this be used safely by real people?" The PoC's job is to be clear, correct, and convincing -- not complete. Adding networking, persistence, and auth to this PoC would triple the code and add zero confidence that the algorithm is correct.</div>
<divclass="part-sub">What to remember from this lecture.</div>
</div>
`
},
{
part: 'Part VIII: Takeaways',
title: 'The Seven Principles',
html: `
<divstyle="line-height:2.4; font-size:15px;">
<div><spanstyle="color:#0969da; font-weight:700;">1.</span><spanclass="em">Make invalid states unrepresentable.</span><br><spanclass="dim"style="margin-left:18px;">Immutable types, private fields, defensive copies. Let the compiler help you.</span></div>
<divstyle="margin-top:8px;"><spanstyle="color:#0969da; font-weight:700;">2.</span><spanclass="em">Separate layers by concern.</span><br><spanclass="dim"style="margin-left:18px;">Math doesn't know about elections. Elections don't know about CLIs.</span></div>
<divstyle="margin-top:8px;"><spanstyle="color:#0969da; font-weight:700;">3.</span><spanclass="em">Thin wrappers, fat libraries.</span><br><spanclass="dim"style="margin-left:18px;">cmd/ parses flags. pkg/ does work. The engine is reusable.</span></div>
<divstyle="margin-top:8px;"><spanstyle="color:#0969da; font-weight:700;">4.</span><spanclass="em">Code should read like the specification.</span><br><spanclass="dim"style="margin-left:18px;">Name types and methods to match the domain. g.Exponentiate(r) not g.Op(r).</span></div>
<divstyle="margin-top:8px;"><spanstyle="color:#0969da; font-weight:700;">5.</span><spanclass="em">Minimize dependencies.</span><br><spanclass="dim"style="margin-left:18px;">Own your core domain. Depend on others for everything else.</span></div>
<divstyle="margin-top:8px;"><spanstyle="color:#0969da; font-weight:700;">6.</span><spanclass="em">Match error handling to context.</span><br><spanclass="dim"style="margin-left:18px;">Errors for external input. Panics for programming bugs. Context matters.</span></div>
<divstyle="margin-top:8px;"><spanstyle="color:#0969da; font-weight:700;">7.</span><spanclass="em">Know what to leave out.</span><br><spanclass="dim"style="margin-left:18px;">A PoC proves the concept. Not every PoC needs a database, REST API, and Docker Compose.</span></div>
</div>
`
},
{
part: 'Part VIII: Takeaways',
title: 'By the Numbers',
html: `
<divclass="stat-grid">
<divclass="stat-box"><divclass="stat-num">6,565</div><divclass="stat-label">Lines of Go</div></div>