Skip to content

About

Federated membership-management platform for associations and political parties (Kotlin/Ktor/KVision) — standard admin (members, accounting, mail-merge, compliance) plus a meritocratic governance layer, sovereign per instance

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

Lapis Cloud

Lapis Cloud — federated membership management with meritocratic governance

Standard membership management, libertarian-extended.
Full association and party administration as the foundation, meritocratic governance as the differentiator.

CI Version Kotlin License Issues Pull Requests Stars Sponsors

About Lapis Cloud

Lapis Cloud is the successor to the PZB (PdV Party Central Bank) — a federated server network with a private-law-association character for the membership management of associations and parties. Every server is sovereign but can federate with other Lapis Cloud instances.

Lapis Cloud covers two orthogonal layers:

  1. Standard membership management — everything a modern association or party administration needs (member master data, contribution management, events, communication, GDPR, reporting, donation receipts, etc.), at a level that makes parallel specialist tools unnecessary.

  2. Innovative libertarian extensions — meritocratic voting, an internal currency ("Libertaler"), internal crowdfunding, pseudonymity with transparency, a right of secession via federation.

The explicit ambition: to become the de facto standard for membership management of associations and parties — completeness over elegance, compliance-first (GDPR, association law, party law, tax law), usable without prior IT knowledge.

Originally developed for the Partei der Vernunft (PdV), Lapis Cloud is open source and open to any organization — political parties, traditional associations, professional bodies, cooperatives, foundations, NGOs.

Tip
Conceptual details, roadmap, and design decisions are maintained in the project vault, not in this repository. This README describes only the technical scope.
  • Lapis Net — a fully decentralized P2P sister project, sharing the same libertarian core principles (meritocratic scoring, self-organization, voluntary association) but differing in implementation (P2P nodes instead of federated servers, cryptographic trust instead of server federation).

  • PZB (https://gitlab.com/pdv7/pzb) — the existing predecessor repository. Kept as a reference (architecture decisions, code patterns) but not adopted 1:1 — Lapis Cloud is a clean reimplementation.

  • Lapis Cloud Mobile — companion app (Kotlin Multiplatform, Android + iOS): login, video-conference join, a home hub that opens the main web sections (including events), and the member-card download. Not in any app store yet. Its section and video features need the optional WebView bridge on the server (off by default, see CHANGELOG.md [0.22.0]); its member tile "Veranstaltungen" uses the section key my-events, which needs a server from v0.29.0 on (an older server answers 400 and the app shows a hint). From v0.30.0 on the server also offers a bridge route and the section key encounter for the encounter space ("Begegnungsraum"); the app has no tile for it yet.

  • kUML — the modeling language used for every diagram in this repository (see below).

  • lapisproject-dev/Lapis-Cloud-Ops (private) — the real, filled-in deployment config (.env, rendered LiveKit/coturn configs, certs, branding) for the instances this project’s maintainer actually operates. This repo’s own deploy/example/ is the generic, public template anyone can self-host from; the Ops repo is the maintainer’s own real-world instantiation of it, kept private because it identifies real organizations and infrastructure. See the NOTE block in deploy/example/README.adoc for the split.

Technology Stack

  • Language: Kotlin

  • Server framework: Ktor

  • Database access: Exposed (Kotlin SQL framework)

  • Database migrations: Flyway

  • Web UI framework: KVision (Kotlin/JS)

  • Frontend-backend communication: Kilua RPC (type-safe RPC between the KVision client and the Ktor server)

  • AI assistance / agentic layer: Koog (JetBrains, Kotlin-native agent framework, multi-LLM without lock-in)

  • Deployment: Docker Compose (deploy/example/). Since v0.31.1 (V1.9.93) the server image is built once per release tag by CI and published to GHCR (ghcr.io/lapisproject-dev/lapis-cloud:<version>); hosts pull it instead of compiling the sources (LAPIS_IMAGE_TAG in .env, rollback = previous tag). The pipeline has run and is verified: the published image ghcr.io/lapisproject-dev/lapis-cloud:0.31.1 (the first image; later tags such as 0.39.0 follow the same route, an instance moves by setting LAPIS_IMAGE_TAG) is public — see docs/architecture/ci-pipeline.adoc and deploy/example/README.adoc. A local source build stays available through docker-compose.build.yml.

Status

Current release: v0.39.0 (database schema V117; a feature release on v0.38.0 with the waves V1.9.200 to V1.9.206 and two fixes. Behaviour changes first: (1) tenders (Ausschreibungen) bound to an adopted resolution, with a list, a detail page and board actions; LTR only, nothing is booked in LTR yet (the payout is a later wave), and guests cannot bid; (2) a menu search in the sidebar and a Ctrl+K / Cmd+K command palette; (3) events are a table with a detail page (registrations overview, seat counter for members, an optional registrant message, CSV export of the registrations); (4) a guided finance setup (Finanzen > Kontenplan & Journal > Einrichtung) with a standard chart of accounts for associations, which is a proposal a tax advisor must confirm; the account mapping moved there from the payment configuration page, and activating online payment now refuses while that mapping is incomplete (a gateway that is already active is not switched off by this); (5) inline field rows with one date-time group, amounts with thousands separators and a stake suggestion in the social compose form; (6) a readable time axis on the price chart. Three additive migrations (V115 to V117); no new environment variable. The staging seed top-up parts matter only on the seeded staging and demo instances. Checked in headless Chrome only: not looked at on real phones or devices, the CSV not opened in a real Excel or LibreOffice, the standard chart not checked against the official DATEV SKR42; see CHANGELOG.md [0.39.0]; underneath it v0.38.0 (database schema V114; a feature release on v0.37.7 with the waves V1.9.182 to V1.9.199 and one contacts-list fix. Behaviour changes first: (1) agreement texts (Vertragstexte) are a table with a detail page, and every text version saved from now on is Markdown (rendered by the server and sanitised; existing versions stay plain and unchanged, the consent hash is unchanged); (2) travel expenses get report attachments (PDF, JPEG, PNG), receipt upload directly in the add form, organisation documents for members (PDF, XLSX, XLS) on the settings page and a Markdown hint text; (3) a new Lapis Cloud logo and favicons (an operator logo keeps priority); (4) a wide page shell and master-detail tables for Gremien, Sitzungen, Anträge (with one decision selector), rooms, catering and shifts; (5) collapsible page intros and a "Hilfe und Feedback" menu, one back button, a unified control bar for the video conference and the encounter room, the LTR account with progressive disclosure and a renamed carpool view; (6) the contacts list no longer shows each contact several times. Three additive migrations (V112 to V114); no new environment variable. Checked in headless Chrome only: not looked at on real phones or devices, in Safari or by a screen reader; no virus scan and no retention period for uploaded travel expense files; see CHANGELOG.md [0.38.0]; underneath it v0.37.7 (database schema V111, unchanged; a client-only release on v0.37.6 with four waves, V1.9.171, V1.9.173, V1.9.180 and V1.9.181. Behaviour changes first: (1) every date and time field of the application offers the browser’s calendar and time picker (event form, travel expenses, volunteer allowances, accounting and SEPA filters, audit log, DSGVO forms and all other screens; the old text field remains as fallback; time fields step in 5 minutes on planning screens and 1 minute elsewhere; year and month filters are number fields); (2) the settings pairs of Auktion, Mahnwesen, Forderungs-Mahnwesen, Online-Zahlung and SEPA-Lastschrift no longer show both 'activate' and 'deactivate' at once, only the applicable one, with the state as text; (3) the travel expense draft shows the days as one full-width row per day, with the return time marked optional and a note that the days update after saving. No migration, no new environment variable. Checked in automated browser tests (headless Chrome) only; nobody clicked the native pickers, and Safari, Firefox, real phones and screen readers were not tried (the picker display follows the browser or operating-system locale, not the application language); see CHANGELOG.md [0.37.7]; underneath it v0.37.6 (database schema V111; a feature release on v0.37.5 with seven waves, V1.9.164 to V1.9.170. Behaviour changes first: (1) the video conference has three more reactions (laughter, amazement, question) and the encounter room offers the same set (plus flowers, and crying as an opt-in per room); (2) the control bar of the encounter room stays in view; (3) the assembly room is built as a theatre (tables centred in the parterre, seats in two loges) and has an optional grid map of the present members (stage 3, wave 1; off by default, switched on per closed assembly room, positions only in server memory, guests and friends never appear on it and get no packet) that opens as a layer from the control bar, with anchor buttons that answer every click; (4) the device picker of the video conference no longer disappears when the browser has not yet allowed camera and microphone (one button asks, on a click only); (5) the online window of an event opens 30 minutes before the start instead of 15, on every instance. One additive migration (V111, tested on PostgreSQL 17); no new environment variable. Looked at by the owner on a staging instance: the hall layout and the map layer; not looked at on real phones, in Safari or by a screen reader, and the stage-3 notice text for the map is still a draft without legal review; a known gap between speaking and hearing in a large room (about five seconds at the 95th percentile in the load test) is not part of this release; see CHANGELOG.md [0.37.6]; underneath it v0.37.5 (database schema V110; a patch release on v0.37.4 with two small waves: nothing changes for the people using the application. The load test showed that the TURN relay of the deployment example ran out of its 20 relay ports with eight relay clients and constant table changes (about a quarter of their connections ran into the time limit); the example now has 100 ports, and the load-test tool stops runs where nobody could enter the room and no longer ends healthy runs on one or two unlucky calls; measured on a test instance with the load-test tool, not with real browsers; no migration, no new environment variable; see CHANGELOG.md [0.37.5]; underneath it v0.37.4, a patch release on v0.37.3 with one wave: nothing changes for the people using the application. The load test of the encounter tables found that, on staging, a coturn on the Docker bridge with external-ip did not relay for clients while LiveKit ran on the same host, so the deployment example now runs coturn in host networking (and documents an nftables rule against UDP replies with TTL 1), the load-test tool can spread its participants over processes and respects the server’s table-change cooldown, and the server gained an unused LiveKit call (updateSubscriptions) for the planned stage 3; verified on staging only with the load-test tool, not with real browsers, and the cause of the TTL 1 replies inside coturn is not understood; no migration, no new environment variable; see CHANGELOG.md [0.37.4]; underneath it v0.37.3, a patch release on v0.37.2 with four small waves: the friend-registration confirmation no longer claims an account was created, table cards show the table top with the seats on a ring (one table per row on a 320 px phone), unavailable options in event rooms are named instead of refused with a generic error, and the release image build falls back to other base-image registries when the ECR pull limit is hit; nothing of it seen in a real browser window, the new CI steps not yet run on GitHub; see CHANGELOG.md [0.37.3]; underneath it v0.37.2, a release on v0.37.1 with two waves: event rooms can be recorded and live-streamed — off by default on three levels (instance switch, release of the single event, start by the moderation), only after everybody who enters has acknowledged the current consent text, with a banner for everybody in the room (one additive migration V110, nothing of it seen in a real browser, call or against a real LiveKit, the consent texts are unreviewed drafts and the legal position depends on the country), and recordings are composed more reliably (bounded video inputs, up to three attempts; not yet confirmed on the real recording that showed the hang); see CHANGELOG.md [0.37.2]; underneath it v0.37.1, a patch release on v0.37.0 with two fix waves: the encounter room seat drawings line up with the seats and the hints and the podium are no longer covered (measured in a browser test, not looked at in a real browser window), and participant recordings no longer let the audio fall behind the picture (proven with generated files; on a real recording only after "Neu berechnen"; existing recordings need the raw files); no migration, no new environment variable, see CHANGELOG.md [0.37.1]; underneath it v0.37.0, a feature release on v0.36.0: messages on a confirmed carpool ride, country of residence and nationality at registration and in the member roster, camera filters (light, colour, skin smoothing) in your own camera image, an optional recording of the pulpit and an optional member finder (both off until an administrator switches them on after an operator notice), encounter entry notices administered per instance (non-members acknowledge the changed notice again), fixed room templates for the encounter space and a load-test tool with a run sheet for the encounter tables — none of it has been seen yet by real people in a real browser window or call, the pulpit recording and the load-test media layer have never run against a real LiveKit, the load-test tool never against a real instance, the skin smoothing was never judged on real faces, the translations were written by the model and every operator notice and consent text is an unreviewed draft; see CHANGELOG.md [0.37.0] for the behaviour changes, the migrations V105 to V109 and the honest limitations). Lapis Cloud contains standard membership management (members, contributions, events, communication, GDPR, accounting), the meritocratic governance layer (voting, elections, systemic consensus, LTR economy), federation, video conferencing and many optional modules.

Features

Each feature has its own document under docs/features/.

Feature Description

Videokonferenzen (V1.0 Wave 1)

Video conferencing, LiveKit-based, for committee sessions; friends can join like guests (V1.9.126), optional noise suppression with an instance default (V1.9.124), reactions and a raised-hand queue (V1.9.127), a display-only timer (V1.9.133)

Tenders (V1.9.201/V1.9.202)

Board-published tasks bound to an adopted resolution; bids in LTR (guests cannot bid), award, acceptance; list and detail screens; no payout yet

Event registrations (V1.9.204)

Events as a table with a detail page, registrations overview, seat counter, registrant message and CSV export

Menu search and command palette (V1.9.203)

Search field in the sidebar and a Ctrl+K / Cmd+K dialog

Finance setup for laypeople (V1.9.206)

Guided setup of chart of accounts and account mapping; standard association chart as a proposal; gate for the payment activation

Payment service providers (Stripe + PayPal)

Card and PayPal checkout for contributions and donations, with webhook handling

Public REST API (V1.3.1)

Read-only machine-to-machine REST API under /api/v1 with API keys

Outbound Webhooks (V1.3.2)

Signed outbound webhooks for fixed domain events

Website Integration (V1.4.1a/V1.4.1b/V1.4.3.3)

Embeddable script for partner websites: login, join link, donation and event registration

Article Module (V1.4.34/V1.4.36)

Editorial article/news workflow with an approval gate

Interessenten-/Sympathisanten-CRM (V1.4.2)

Contact management for prospects and supporters who are not members

Bank Statement Import (V1.4.5.1 / V1.4.5.1.1)

CSV and MT940 bank statement upload with matching against open contributions

DATEV Export (V1.4.5.2)

DATEV-EXTF Buchungsstapel export of posted journal entries

Contribution relief (deferral, exemption, reduction) (V1.4.10)

Member requests for deferral, exemption or reduction of contributions

Travel expense reimbursement (V1.4.11, PdV form V1.9.122)

Self-service travel expense reports following the PdV form: a day grid with tiered day allowances and meal deductions, mileage with passengers, receipted costs, advance and payout or donation waiver, and a SEPA credit transfer file (pain.001, V1.9.123; never tested with a real bank)

Volunteer/instructor allowance (V1.4.12)

Tax-privileged volunteer and instructor payments with annual caps

AI assistance (optional, default off) (V1.6.1)

Optional statute Q&A with verified citations (off by default)

Member map ("Vorstands-Karte", V1.9.5-V1.9.9)

Board-only aggregate map of member postal-code distribution

Member counts over time (V1.9.59)

Member count history per status

SuperMailer (V1.9.7/V1.9.15)

HTML mailing content and asynchronous send path

Dynamic and mandatory mailing lists (V1.9.111)

Mailing lists whose recipients are computed from a rule at send time; mandatory lists without opt-out

Rule-based committees (V1.9.112)

Committees whose members are computed from a rule instead of seat rows; a vote freezes its electorate when it is opened

Online participation in events (V1.9.113)

Lapis video conference created on the first join, entry into an encounter space, guests without an account

Public member count toggle (V1.9.10)

Setting to show or hide the active member count on public pages

Public icon navigation + overview pages (V1.9.11)

Icon navigation and overview pages for the public site

Mitfahrzentrale (V1.9.12, passengers V1.9.125)

Carpooling bulletin board for members; since V1.9.125 guests and friends can ride along (six methods open to them)

Regional chapters ("Gliederungsverwaltung", Landesverbände) (V1.9.13/V1.9.14)

Optional regional chapters with chapter-scoped officer access

Membership tiers (V1.9.18)

Management of membership tiers and their amounts

Member photo and public profiles (V1.9.19-V1.9.21)

Voluntary member photos and public profiles with consent

Democratic elections (V1.9.22/V1.9.23)

Election lifecycle screen: committee, candidacies, voting booth, results

Voting in the conference room (V1.9.24-V1.9.27)

Voting panel inside the video-conference room

Systemic consensus web client (V1.9.28)

Web client for systemic consensus (Konsensieren)

Opinion polls (V1.9.30/V1.9.31)

Non-binding anonymous opinion polls

Quick start

Self-hosting with Docker Compose: see deploy/example/README.adoc (quick start, updating, backup and restore, optional modules).

Documentation Convention

Consistent across all Lapis and kUML projects (see CLAUDE.md):

  • All documentation in Asciidoctor (.adoc) — no README.md

  • All diagrams in kUML, no PlantUML/Mermaid/draw.io/ASCII art

  • Diagrams embedded via the [kuml] macro of the kuml-asciidoc extension (Maven Central) — source inline in the .adoc document is the single source of truth, never replaced by a pre-rendered image. Exception: GitHub’s built-in .adoc viewer does not load the extension, so it cannot execute [kuml] blocks — for diagrams meant to be visible there (like the conference-room diagram in docs/features/video-conferencing.adoc), commit a companion image::docs/images/<name>.svg[…​] reference immediately above the [kuml] block, purely as a GitHub-preview fallback, and re-render it by hand whenever the model changes (see the note above the diagram in docs/features/video-conferencing.adoc for the exact command). Nothing enforces that the two stay in sync — this is a deliberate, manual trade-off, not an automated build step.

[kuml, filename-without-extension, svg]

<kUML source>


Branch and Development Workflow

  • The default branch is always master, never main

  • Feature branches stay local and are never pushed

  • Releases happen via a local squash-merge onto master, then push

  • Never --force push without an explicit instruction

Details: CLAUDE.md in this repository.

License

Apache License 2.0 — see LICENSE.

About

Federated membership-management platform for associations and political parties (Kotlin/Ktor/KVision) — standard admin (members, accounting, mail-merge, compliance) plus a meritocratic governance layer, sovereign per instance

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages