Assembley

Security & Trust

Built for secure decisions

Assembley is designed from the ground up for governance, where every action must be auditable.

Security at a glance

Identity

Access is a single-use, time-limited ballot link scoped to one voter and one assembly. No passwords, no shared credentials.

Encryption

Connections are encrypted in transit: HTTPS only, HTTP redirected, strict transport security set. Sessions are stored in httpOnly cookies invisible to JavaScript.

Access control

Row-level security separates each organisation's data, and roles separate what a voter and an administrator can reach. On a secret ballot the vote row carries no voter at all.

Infrastructure

The database runs in Frankfurt and the application's functions in the same region. What the sub-processor agreements permit is wider, and two of them name the United States.

Attestation

A hash-chained event log, a Merkle root per agenda item, and an evidence package a third party can recompute without access to our systems.

Monitoring

Administrative actions and governance events are appended to logs whose triggers refuse UPDATE and DELETE. Nothing watches them: the rate limiters refuse abuse, and refusing is not monitoring.

iA summary is not the documentation. This page is what Assembley states.

Ask AI to explain. Open a summary of this security documentation in plain language.

Overview

Assembley handles governance voting for companies, associations, and organisations across Europe. The security model is built around three things: controlled access, vote integrity, and a record that can be checked afterwards.

If a vote is challenged, you can produce the recorded chain of governance events: who voted, when, and in which order. For secret-ballot items the record attests participation and the ballot set, not who chose what. A trigger refuses UPDATE and DELETE on that chain and on the votes themselves, so it cannot be rewritten afterwards by anyone, including Assembley. That is not a policy commitment; it is enforced at the database level.

Identity

Access is a single-use link scoped to one voter and one assembly. No passwords. No shared credentials. What that link is worth is set by the organisation running the assembly.

Integrity

Votes are write-once at the database level. No administrator, including Assembley, can modify or delete a submitted vote.

Auditability

Governance events are recorded with a timestamp and the hash of the one before. The record is self-contained and independently verifiable.

VotersVerify identityEvent hashedEvent loggedVote sealedLive resultsForAgainstAbstainAudit chainSHA-25606b80921SHA-256ff2b6839SHA-2566122e015SHA-256aa2b58cdSHA-256a88c0d5cChain intact

The diagram above shows a single vote moving through Assembley's pipeline. When a voter submits their ballot, the server verifies the session against the assembly, writes the vote, computes a hash of the event, and appends it to the chain. On an identified ballot the vote and its audit entry are written in one database transaction, so neither can exist without the other. A secret ballot is the deliberate exception: it writes no audit entry, because the fields in one would name the voter.

Identity layer

Every participant is identified to the system before a governance action is accepted, and the system does not rely on passwords. What that identification is worth is a setting the organisation chooses.

How magic links work

  1. 1SystemBefore assemblyA unique, cryptographically random ballot link is generated for each voter and sent to their registered email address.
  2. 2VoterDay of assemblyThe voter clicks their personal link. No typing, no password, no app required. Works on any device.
  3. 3ServerVerificationThe link is validated server-side: checked for expiry, single-use status, and that it belongs to the correct assembly.
  4. 4ServerSingle-useThe link is invalidated on first use. It cannot be forwarded or reused, even if intercepted.
  5. 5ServerSessionA session is issued, stored in an httpOnly cookie invisible to JavaScript, and used to authenticate every subsequent action.
  6. 6BrowserOngoingThe session is re-verified on every vote submission, not just at sign-in.

How people join

Self-registered voters

Participants join by QR code or the meeting link, register themselves and confirm with a one-time code sent to their email. The chair accepts or rejects each registration. There is no register: everyone accepted has one vote, and nobody holds a proxy.

Invited voters

Members come from the organisation's register and receive a personal link by email. The link is not enough on its own: the voter must also enter a code shown while the assembly is live. Votes follow the register, and members can give proxies.

Extra identity verification (eID)

An add-on to invited meetings: an electronic-ID check on top of the link and the code. No session is issued until the identity provider has answered. That callback is the only path that mints one. Built, and not yet offered for new meetings.

How participants joined is recorded on the assembly when it opens, and printed in its evidence package. Assemblies set up before these two ways existed keep the setup they were created with, and their records keep the wording they were issued with.

Rate limiting

  • Requests to re-send a ballot link are capped per IP address within a window.
  • A second link is not sent to the same address for the same assembly inside a cooldown.
  • One-time codes are capped per email address, with a separate ceiling per address sized for a room full of people on one network.
  • The re-send path answers identically whether or not the address is on the roster, so it cannot be used to test which addresses exist.

Link security

  • High-entropy random token: computationally unguessable
  • Single-use: invalidated immediately on first access
  • Time-limited: expires automatically after the assembly
  • Scoped to one assembly: cannot be used elsewhere

Session security

  • Session cookie is invisible to JavaScript (XSS-resistant)
  • Secure and HTTPS-only under production: cannot be sent over HTTP.
  • SameSite=Strict, so the cookie is not attached to a request arriving from another site.
  • Sessions expire automatically: no persistent access

What entry records

  • Magic-link attempts are recorded with the address, the outcome and the time.
  • An electronic-ID verification enters the governance chain, carrying the assurance the provider actually returned, including when it returns none.
  • Entering a meeting code updates a presence row rather than appending an event, so a second entry overwrites the record of the first.
  • How participants joined is recorded per assembly, when it opens, not per claim about a person.

Where this stops

  • Assembley does not verify that a person is who the organisation says they are. Which level of assurance applies is the organisation's configuration, and at the lowest level it means only that an address was on a list.

Execution layer

Votes are not stored as rows that get edited. Each is written once, and a trigger refuses UPDATE and DELETE on the table. Results are derived from what was written, not from a running total anyone can adjust.

Event sourcing model

  1. 1

    Event written

    Single INSERT

  2. 2

    Hash computed

    Over event payload

  3. 3

    Appended to chain

    prev_hash included

Vote submission: validation layers

  • Session verifiedThe voter's session is verified on every submission, not just at sign-in.
  • Assembly must be liveVotes are rejected if the assembly has not started or has already ended.
  • Voting window enforcedThe administrator controls exactly when voting opens and closes for each agenda item. No votes are accepted outside this window.
  • One vote per itemEach voter can submit exactly one vote per agenda item. Duplicate submissions are rejected at the database level, not just in application code.
  • Vote and audit written togetherThe vote record and its audit entry are written in a single database transaction. A secret ballot is the exception and writes no audit entry, because the fields in one would name the voter.
  • A vote cannot be changed or deletedOnce written, a vote cannot be modified or deleted by anyone, including system administrators. This is enforced at the database level, not by access controls alone.
  • Merkle root updatedAfter each vote, the Merkle root for the agenda item is recomputed. Any modification to any prior vote would change the root.
  • Event chain integrityEach audit entry includes the hash of the previous entry: breaking the chain at any point is detectable.

Weighted voting

  • Each participant carries a voting weight set by the organisation.
  • Results are calculated on voting weight, not headcount.
  • Proxy votes are added to the representative's weight.
  • The administrator sees weighted counts as they arrive.

Administrator-controlled voting windows

  • Voting opens only when the administrator explicitly opens it
  • Closes immediately when the administrator moves on
  • Every voter is pushed the same state over a realtime channel.
  • Votes submitted outside the window are rejected server-side

What is frozen, and when

When an assembly opens, the figures it will be counted against are frozen: the total voting rights, the share capital basis, the shareholder count, and the quorum configuration. Each agenda item freezes its majority requirement and its secrecy when voting opens on it. The voter's name and weight are frozen onto the ballot as it is written, so a later change to the register cannot rewrite what was cast.

Atomic guarantees

An identified vote and its audit entry are written in a single database transaction; there is no state where one exists without the other. A secret ballot writes the ballot and its receipt in one transaction and no audit entry at all.

Audit layer

Every governance event is appended to a hash-chained log. Tampering with any historical record breaks the chain from that point forward, detectable by any party with access to the log.

Hash chain structure

  1. Event N−1

    hash: abc123

  2. Event N

    prev: abc123

    hash: def456

  3. Event N+1

    prev: def456

    hash: …

Each event's hash includes the previous hash, forming a tamper-evident chain.

Merkle roots

  • After voting closes, a Merkle root is computed from all votes
  • The root is a single hash representing the complete vote set.
  • Change any vote and the root changes: tampering is detectable
  • Roots are stored alongside the event chain, in a table whose trigger refuses UPDATE and DELETE.

Evidence package

  • Generated after the assembly closes
  • Contains the full event chain, Merkle roots, attendance, and results
  • The events file is stored uncompressed, so the SHA-256 of those bytes is the Verification ID printed on the PDF.
  • It carries the stored root, the recomputed root and the leaf scheme per item, so a third party can redo the arithmetic without access to Assembley.

Secret ballots: unattributed, still verifiable

Your own verification receipt

When the meeting ends, your browser shows you the verification code of each secret ballot you cast, to save. After voting closes, you can find that exact code in the published record and confirm your ballot was counted, without revealing how you voted. The code is deliberately non-transferable: it cannot prove your choice to anyone else, so it gives a vote-buyer or coercer nothing to verify.

Unattributed, verifiable evidence

For a secret item, the evidence package proves the result without naming a single voter: the final tally, the full set of unattributed ballot identifiers, a Merkle root fixing that exact set of ballots, a commitment to who was entitled to vote, and a reconciliation showing the number of ballots equals the number of recorded participants (the check that proves no one voted twice). An outside auditor can verify every line; none of it links a ballot to a person.

Where secrecy has a limit: where shareholders hold very different numbers of shares, an unusually large holding can sometimes be inferred from the published totals. We would rather name the one place secrecy thins out than let it surprise someone later.

Events logged

  • Voter sign-in

    IP address, email address, assembly, outcome, time

  • Failed sign-in attempt

    IP address, email address, time

  • Vote submitted (identified ballot)

    Participant, agenda item, choice, IP address, device, time

  • Vote submitted (secret ballot)

    Agenda item, ballot code, choice. No voter, no address, no device

  • Assembly started / ended

    Administrator, time

  • Voting opened / closed

    Agenda item, administrator, time

  • Invitation sent

    Recipient, assembly, time

  • Proxy registered

    Grantor, representative, administrator, time

  • Document exported

    Who took a copy, of which assembly, and the hash of what they hold

Where this stops

  • Reading a record is not logged. The log records what was written and what was exported, not who looked at a result or a roster.
  • Nothing watches for unusual activity. The rate limiters refuse abuse, and refusing is a control rather than monitoring. No alert is raised and nobody is notified.

Vote lifecycle

A single vote passes through five deterministic stages. Each stage is independently verifiable.

  1. 1Voter session verifiedMagic link token validated server-side, session issued.
  2. 2Voting window confirmedServer checks the assembly is live and the item is open for voting.
  3. 3Vote event writtenA single INSERT. A duplicate is rejected by a database constraint.
  4. 4Audit entry appendedWritten in the same transaction as the vote. A secret ballot writes a receipt instead, carrying the voter and not the choice.
  5. 5Merkle root updatedVote set for this agenda item rehashed and stored.

System trust model

Four precise statements about what the system does. No qualifications, no marketing language.

1Governance outcomes are not read out of a total anybody can edit. They are counted from the votes as written.
2Auditability is architectural. It is not a feature added on top; it is the mechanism by which the system operates.
3No administrator, including Assembley, can modify or delete a submitted vote. This is enforced at the database level, not by access controls.
4The evidence package is self-contained. A lawyer or auditor can verify integrity without access to Assembley systems.

Incident transparency

Assembley is designed so that the consequences of a failure are bounded and detectable. Votes are written once and every governance event is hash-chained, so a record altered after the fact breaks the chain at a point any reader can find.

What is watched, and what is not?

Nothing watches for unusual activity and no alert is raised. Failed sign-ins, rate-limit refusals and every administrative action are recorded and visible in the audit trail; reading them is something a person has to do.

What does the evidence package contain?

The full event chain, Merkle roots per agenda item, attendance records, vote results, and timestamps. The events file is stored uncompressed so its SHA-256 is the Verification ID on the PDF, and any modification after generation changes it. It can be verified by a lawyer or auditor without access to Assembley systems.

Can Assembley alter a submitted vote?

No. A trigger blocks UPDATE and DELETE on the votes table at the database level. This applies to every user including Assembley administrators. It is architectural, not a policy.

What happens if Assembley is unavailable?

Evidence packages generated before an outage remain valid and independently verifiable. The record does not depend on Assembley being online to be checked.

Data & privacy

Assembley is built for European organisations. Data is stored in the EU, processed under a data processing agreement, and handled according to data minimisation principles. Where processing may occur is set by the sub-processor agreements rather than by a region setting, and those agreements are summarised in the published sub-processor list.

Data residency

  • The database runs in AWS eu-central-1, Frankfurt.
  • The application's functions run in the same region, moved there on 10 September 2026.
  • Transactional mail is sent from eu-west-1, Ireland.
  • Two of the three sub-processor agreements state that primary processing takes place in the United States. The sub-processor list carries both the agreement and the console reading, and does not resolve them into one sentence.

Data minimisation

  • Only the data needed to run an assembly is collected
  • The Services are designed to run on a name, an email address and a voting entitlement.
  • There is no advertising and no tracking pixel. If you allow analytics in the cookie settings, the site measures visits and page speed with Vercel Web Analytics and Speed Insights. That data is not sold.
  • Ballot links contain no personal information.

Encryption

  • All connections are encrypted in transit, with HTTP redirected and strict transport security set for two years.
  • Passwords, where they are used at all, are held only by the authentication provider and never by this application.
  • Ballot tokens are stored only as SHA-256 hashes, never in the form that was emailed.
  • No secret or credential is kept in the source code. A local build refuses to finish if it has picked up a production database address.

GDPR

  • The Data Processing Agreement is published, not available on request.
  • Right to erasure: a request is handled by the organisation as controller, and the share register is deletable by a super admin.
  • Data portability: full export available
  • No third-party data sharing without consent
  • Row-level security is enabled on every table, so one organisation's rows are not reachable from another's session.
  • No advertising, no tracking pixels, and no analytics resale.

What each role can access

Participant

What a voter can see

  • Can: Their own identity and voting weight
  • Can: The agenda and item descriptions
  • Can: Their own submitted votes
  • Can: Whether the assembly is live or ended
  • Cannot: Other participants' identities or votes
  • Cannot: Results before the assembly ends, where the organisation has chosen to withhold them
  • Cannot: Administrative controls or settings
Administrator

What an admin can see

  • Can: The full participant list with voting weights
  • Can: The number of ballots cast as they arrive; a secret item's choices only once voting on it has closed
  • Can: Registered presence, and the figures the organisation configured to measure it against
  • Can: The assembly event log and audit trail
  • Can: Results after the assembly ends, and exportable minutes
  • Cannot: With a secret ballot, the administrator sees the totals, never an individual ballot.
  • Cannot: Any change to a vote once submitted

What Assembley does not do

  • No advertising, tracking pixels, or analytics resale, ever.
  • No third-party data sharing without explicit written consent.
  • No persistent user profiles beyond what is needed to run an assembly.
  • No secrets or credentials stored in source code or version control.

Where this stops

  • Assembley holds no third-party security certification. Nothing here has been audited by anyone outside the company.
  • The database is backed up automatically once a day, on the paid database plan, and each backup is kept for about seven days. There is no point-in-time recovery yet, so a restore returns the database to the most recent daily backup. Uploaded files, such as candidate photos, are not part of the backup.
  • Nothing is deleted on a timer. The retention periods in the Data Processing Agreement are honoured by acting on a request, not by an automatic purge.
  • Access to production is not reviewed on a schedule, and administrative access is an elevation of an ordinary account rather than a separate credential.
  • Nothing checks dependencies for known vulnerabilities on a schedule.

Reporting a vulnerability

Write to security@assembley.co. Tell us what you found, how to reproduce it, and what you think it lets someone do. We do not publish a PGP key; if you need to send something encrypted, ask and we will arrange it.

Clause 34.3 of the Terms of Service makes testing conducted in accordance with this process an exception to the acceptable-use prohibition. Testing outside it is not covered.

What is in scope

  • assembley.co, including the application served from it, and assembley.dk and www.assembley.dk, which redirect to it

What is out of scope

  • Denial of service, load testing, and anything that degrades the service for others
  • Social engineering of our people, our customers, or their members
  • Physical attacks against offices or hardware
  • Third-party services we use but do not operate (report those to their owners)
  • Findings that require access to another customer’s account, or credentials you were not given
  • Automated scanning at volume

Rules

  • Do not access, modify or delete data belonging to anyone else. If you reach someone else’s data by accident, stop and tell us what you did.
  • Do not remove data from the system. A screenshot of a single record is evidence; a copy of a table is not.
  • Stop at proof of concept. Demonstrating that something is possible is the finding; going further is not.
  • Do not disclose publicly until we have agreed a date with you.

What we commit to

  • We confirm we have received your report.
  • We keep you informed while we are working on it.
  • We tell you when it is resolved.
  • We agree a disclosure date with you rather than imposing one.
  • We will not pursue legal action for good-faith research conducted within these rules, and we will say so in writing if you ask.

We do not offer a bounty. We would rather say so than leave it open.

Statement of scope

Quoted from Annex II §10 of the Data Processing Agreement, which is the binding form of it. The measures on this page are described there; nothing here adds to them.

Assembley holds no third-party security certification as at the date of this DPA. The measures above are described as implemented; they are not certified by an external auditor, and Assembley makes no representation that they render Customer Personal Data secure against all forms of attack or compromise.