diff --git a/.gitignore b/.gitignore index 19a1743..bd68b84 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,11 @@ docs/internal/ # AI development workflow files master-prompt.md scripts/ai_team.py + +# LaTeX build artifacts +paper/*.aux +paper/*.bbl +paper/*.blg +paper/*.log +paper/*.out +paper/*.pdf diff --git a/paper/Makefile b/paper/Makefile new file mode 100644 index 0000000..951ecb1 --- /dev/null +++ b/paper/Makefile @@ -0,0 +1,22 @@ +MAIN = fapp +BIB = fapp-refs + +.PHONY: all clean watch + +all: $(MAIN).pdf + +$(MAIN).pdf: $(MAIN).tex $(BIB).bib + pdflatex -interaction=nonstopmode $(MAIN) + bibtex $(MAIN) + pdflatex -interaction=nonstopmode $(MAIN) + pdflatex -interaction=nonstopmode $(MAIN) + +clean: + rm -f $(MAIN).{aux,bbl,blg,log,out,pdf,toc,lof,lot,fls,fdb_latexmk,synctex.gz} + +watch: + @echo "Watching for changes..." + @while true; do \ + inotifywait -qe modify $(MAIN).tex $(BIB).bib 2>/dev/null || sleep 2; \ + $(MAKE) all; \ + done diff --git a/paper/fapp-refs.bib b/paper/fapp-refs.bib new file mode 100644 index 0000000..7779e61 --- /dev/null +++ b/paper/fapp-refs.bib @@ -0,0 +1,263 @@ +@misc{rfc9000, + author = {Jana Iyengar and Martin Thomson}, + title = {{QUIC}: A {UDP}-Based Multiplexed and Secure Transport}, + howpublished = {RFC 9000}, + year = {2021}, + month = may, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC9000}, +} + +@misc{rfc9420, + author = {Richard Barnes and Benjamin Beurdouche and Raphael Robert and Jon Millican and Emad Omara and Katriel Cohn-Gordon}, + title = {The Messaging Layer Security ({MLS}) Protocol}, + howpublished = {RFC 9420}, + year = {2023}, + month = jul, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC9420}, +} + +@misc{rfc8032, + author = {Simon Josefsson and Ilari Liusvaara}, + title = {Edwards-Curve Digital Signature Algorithm ({EdDSA})}, + howpublished = {RFC 8032}, + year = {2017}, + month = jan, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC8032}, +} + +@misc{rfc7748, + author = {Adam Langley and Mike Hamburg and Sean Turner}, + title = {Elliptic Curves for Security}, + howpublished = {RFC 7748}, + year = {2016}, + month = jan, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC7748}, +} + +@misc{rfc8439, + author = {Yoav Nir and Adam Langley}, + title = {{ChaCha20} and {Poly1305} for {IETF} Protocols}, + howpublished = {RFC 8439}, + year = {2018}, + month = jun, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC8439}, +} + +@misc{rfc5869, + author = {Hugo Krawczyk and Pasi Eronen}, + title = {{HMAC}-Based Extract-and-Expand Key Derivation Function ({HKDF})}, + howpublished = {RFC 5869}, + year = {2010}, + month = may, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC5869}, +} + +@misc{rfc8949, + author = {Carsten Bormann and Paul Hoffman}, + title = {Concise Binary Object Representation ({CBOR})}, + howpublished = {RFC 8949}, + year = {2020}, + month = dec, + publisher = {Internet Engineering Task Force}, + doi = {10.17487/RFC8949}, +} + +@article{bpt2022wartezeiten, + author = {{Bundespsychotherapeutenkammer}}, + title = {{BPtK}-Studie: Wartezeiten in der ambulanten psychotherapeutischen Versorgung}, + journal = {BPtK Forschung}, + year = {2022}, + note = {Available at \url{https://www.bptk.de}}, +} + +@article{bpt2024versorgung, + author = {{Bundespsychotherapeutenkammer}}, + title = {Ein Jahr nach der Reform der Psychotherapie-Richtlinie}, + journal = {BPtK Forschung}, + year = {2024}, + note = {Available at \url{https://www.bptk.de}}, +} + +@article{jacobi2014psychische, + author = {Frank Jacobi and Michael H{\"o}fler and Jens Strehle and Simon Mack and Axel Gerschler and Lucie Scholl and Manfred E. Beutel and Wolfgang Maier and Borwin Bandelow and Harald Jurgen Freyberger and Hans-Ulrich Wittchen}, + title = {Mental disorders in the general population: Study on the health of adults in {Germany} and the additional module mental health ({DEGS1-MH})}, + journal = {Der Nervenarzt}, + volume = {85}, + number = {1}, + pages = {77--87}, + year = {2014}, + doi = {10.1007/s00115-013-3961-y}, +} + +@article{schlack2023mental, + author = {Robert Schlack and Heike Hölling and Liane Sann and Christian Schmidt and Elvira Mauz and Thomas Lampert}, + title = {Mental health of children and adolescents during the {COVID-19} pandemic}, + journal = {Journal of Health Monitoring}, + volume = {8}, + number = {S1}, + year = {2023}, + doi = {10.25646/11043}, +} + +@inproceedings{goldschlag1996onion, + author = {David M. Goldschlag and Michael G. Reed and Paul F. Syverson}, + title = {Hiding Routing Information}, + booktitle = {Information Hiding: First International Workshop}, + pages = {137--150}, + year = {1996}, + publisher = {Springer}, + doi = {10.1007/3-540-61996-8_37}, +} + +@article{lora2015semtech, + author = {{Semtech Corporation}}, + title = {{LoRa} Modulation Basics}, + journal = {Semtech Application Note AN1200.22}, + year = {2015}, +} + +@misc{loraalliance2020, + author = {{LoRa Alliance}}, + title = {{LoRaWAN} Specification v1.0.4}, + year = {2020}, + note = {Available at \url{https://lora-alliance.org/resource-hub/}}, +} + +@misc{eu868dutycycle, + author = {{European Telecommunications Standards Institute}}, + title = {{ETSI} {EN} 300 220: Short Range Devices ({SRD})}, + year = {2019}, + note = {Electromagnetic compatibility and Radio spectrum Matters}, +} + +@inproceedings{borisov2004offrecord, + author = {Nikita Borisov and Ian Goldberg and Eric Brewer}, + title = {Off-the-Record Communication, or, Why Not to Use {PGP}}, + booktitle = {Proceedings of the 2004 ACM Workshop on Privacy in the Electronic Society}, + pages = {77--84}, + year = {2004}, + doi = {10.1145/1029179.1029200}, +} + +@inproceedings{douceur2002sybil, + author = {John R. Douceur}, + title = {The Sybil Attack}, + booktitle = {Peer-to-Peer Systems: First International Workshop (IPTPS 2002)}, + pages = {251--260}, + year = {2002}, + publisher = {Springer}, + doi = {10.1007/3-540-45748-8_24}, +} + +@inproceedings{meshtastic2023, + author = {{Meshtastic Project}}, + title = {Meshtastic: Open Source Long Range Mesh Communicator}, + year = {2023}, + note = {Available at \url{https://meshtastic.org}}, +} + +@misc{reticulum2023, + author = {Mark Qvist}, + title = {Reticulum: Cryptography-based networking for wide-area and local networks}, + year = {2023}, + note = {Available at \url{https://reticulum.network}}, +} + +@misc{briar2017, + author = {{Briar Project}}, + title = {Briar: Secure Messaging, Anywhere}, + year = {2017}, + note = {Available at \url{https://briarproject.org}}, +} + +@inproceedings{danezis2003mixminion, + author = {George Danezis and Roger Dingledine and Nick Mathewson}, + title = {Mixminion: Design of a Type {III} Anonymous Remailer Protocol}, + booktitle = {IEEE Symposium on Security and Privacy}, + pages = {2--15}, + year = {2003}, + doi = {10.1109/SECPRI.2003.1199323}, +} + +@article{bernstein2012chacha, + author = {Daniel J. Bernstein}, + title = {The {ChaCha} family of stream ciphers}, + year = {2008}, + note = {Available at \url{https://cr.yp.to/chacha.html}}, +} + +@misc{sgbv2024, + title = {{Sozialgesetzbuch ({SGB}) F{\"u}nftes Buch -- Gesetzliche Krankenversicherung}}, + note = {Sections 92, 95, 101. Available at \url{https://www.gesetze-im-internet.de/sgb_5/}}, + year = {2024}, +} + +@misc{kbvarztsuche, + author = {{Kassenärztliche Bundesvereinigung}}, + title = {{KBV} Arztsuche}, + year = {2024}, + note = {Available at \url{https://www.kbv.de/html/arztsuche.php}}, +} + +@misc{doctolib2024, + author = {{Doctolib GmbH}}, + title = {Doctolib: Online-Terminbuchung}, + year = {2024}, + note = {Available at \url{https://www.doctolib.de}}, +} + +@misc{terminservice116117, + author = {{Kassenärztliche Bundesvereinigung}}, + title = {Terminservicestellen der {KV} -- 116117}, + year = {2024}, + note = {Available at \url{https://www.116117.de}}, +} + +@article{mandl2007indivo, + author = {Kenneth D. Mandl and Isaac S. Kohane}, + title = {Tectonic Shifts in the Health Information Economy}, + journal = {New England Journal of Medicine}, + volume = {358}, + number = {16}, + pages = {1732--1737}, + year = {2008}, + doi = {10.1056/NEJMsb0800220}, +} + +@inproceedings{benet2014ipfs, + author = {Juan Benet}, + title = {{IPFS} -- Content Addressed, Versioned, {P2P} File System}, + year = {2014}, + note = {arXiv preprint arXiv:1407.3561}, +} + +@inproceedings{hkdf2010krawczyk, + author = {Hugo Krawczyk}, + title = {Cryptographic Extraction and Key Derivation: The {HKDF} Scheme}, + booktitle = {Advances in Cryptology -- CRYPTO 2010}, + pages = {631--648}, + year = {2010}, + publisher = {Springer}, + doi = {10.1007/978-3-642-14623-7_34}, +} + +@article{dgppn2019leitlinie, + author = {{DGPPN}}, + title = {S3-Leitlinie Psychosoziale Therapien bei schweren psychischen Erkrankungen}, + journal = {AWMF-Register}, + year = {2019}, + note = {Available at \url{https://www.awmf.org}}, +} + +@article{who2022mental, + author = {{World Health Organization}}, + title = {World Mental Health Report: Transforming Mental Health for All}, + year = {2022}, + note = {Available at \url{https://www.who.int}}, +} diff --git a/paper/fapp.tex b/paper/fapp.tex new file mode 100644 index 0000000..85920a3 --- /dev/null +++ b/paper/fapp.tex @@ -0,0 +1,926 @@ +\documentclass[11pt,a4paper]{article} + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage[margin=2.5cm]{geometry} +\usepackage{amsmath,amssymb} +\usepackage{graphicx} +\usepackage{booktabs} +\usepackage{tabularx} +\usepackage{hyperref} +\usepackage{listings} +\usepackage{xcolor} +\usepackage{enumitem} +\usepackage{float} +\usepackage{url} + +\hypersetup{ + colorlinks=true, + linkcolor=blue!60!black, + citecolor=green!50!black, + urlcolor=blue!70!black, +} + +\lstset{ + basicstyle=\ttfamily\small, + breaklines=true, + frame=single, + framerule=0.4pt, + rulecolor=\color{gray!50}, + backgroundcolor=\color{gray!5}, + numbers=left, + numberstyle=\tiny\color{gray}, + numbersep=6pt, + columns=fullflexible, + keepspaces=true, + xleftmargin=1.5em, + xrightmargin=0.5em, +} + +\newcommand{\fapp}{\textsc{Fapp}} +\newcommand{\qpq}{\textsc{QuicProQuo}} +\newcommand{\cbor}{\textsc{Cbor}} + +\title{\textbf{FAPP: A Privacy-Preserving Decentralized Protocol\\for Psychotherapy Appointment Discovery}} + +\author{ + Christian Nennemann\\ + Independent Researcher\\ + \texttt{write@nennemann.de} +} + +\date{April 2026} + +\begin{document} + +\maketitle + +\begin{abstract} +In Germany, patients seeking psychotherapy face wait times of three to six months, +driven in part by structural opacity in the appointment allocation system of the +\emph{Kassenärztliche Vereinigung} (KV). We present FAPP (Free Appointment +Propagation Protocol), a decentralized protocol that enables licensed +psychotherapists to announce free appointment slots into a mesh network, where +patients can discover and reserve them anonymously. FAPP implements an +\emph{asymmetric privacy model}: therapist identities are public and +cryptographically bound to their professional license (Approbation), while +patient queries carry no identifying information. Reservations are end-to-end +encrypted using X25519 Diffie--Hellman key agreement with ChaCha20-Poly1305 +authenticated encryption, ensuring that only the intended therapist can read +patient contact information. The protocol is transport-agnostic, supporting +QUIC, TCP, and LoRa links through the \qpq{} mesh networking stack. We +describe the protocol design, analyze its security properties against a +realistic adversary model grounded in German healthcare regulation, and +discuss deployment considerations for a real-world pilot. +\end{abstract} + +\medskip +\noindent\textbf{Keywords:} decentralized healthcare, privacy-preserving discovery, mesh networking, psychotherapy access, appointment scheduling + +% =========================================================================== +\section{Introduction} +\label{sec:intro} +% =========================================================================== + +Mental disorders affect approximately 27.8\% of the adult population in Germany +in any given year~\cite{jacobi2014psychische}, yet the infrastructure for +connecting patients with psychotherapists remains rooted in centralized, +opaque systems. The Kassenärztliche Vereinigung (KV)---the self-governing +body of statutory health insurance physicians---operates a \emph{Terminservicestelle} +(appointment referral service) reachable via the national number +116117~\cite{terminservice116117}. Studies by the Bundespsychotherapeutenkammer +(BPtK) consistently report average wait times of three to six months between +initial contact and the first therapeutic session~\cite{bpt2022wartezeiten}, +with the situation worsening for child and adolescent psychotherapy and in +rural regions. + +The structural problem is one of \emph{visibility}. A therapist with a free +50-minute slot next Tuesday has no efficient channel to make this slot +discoverable to the patients who need it. The KV's 116117 system operates +on a referral basis with limited real-time slot data. Commercial platforms +such as Doctolib~\cite{doctolib2024} aggregate some appointment data but +require therapists to opt in, charge fees, and track patient search +behavior~\cite{bpt2024versorgung}. The KBV's own physician search +portal~\cite{kbvarztsuche} provides practice information but not real-time +slot availability. None of these systems allow patients to search +\emph{anonymously}---a property of particular importance in mental health, +where the mere act of searching for a therapist can carry stigma. + +We propose FAPP (Free Appointment Propagation Protocol), a decentralized +protocol designed to address this specific gap. FAPP operates over the +\qpq{} mesh network~\cite{rfc9000}, enabling therapists to announce free +appointment slots and patients to discover them without any central server, +registration, or identity disclosure. The protocol enforces an +\emph{asymmetric privacy model}: therapists, as licensed professionals +(\emph{Approbation}, regulated under SGB~V \S\S~92, 95~\cite{sgbv2024}), +operate with public, verifiable identities, while patients enjoy query-level +anonymity. Reservation messages are end-to-end encrypted so that +intermediary mesh nodes cannot observe patient contact information. + +The contributions of this paper are: +\begin{enumerate}[nosep] + \item A complete protocol specification for decentralized, privacy-preserving + appointment discovery tailored to the German psychotherapy system + (Section~\ref{sec:protocol}). + \item An asymmetric privacy model with formal threat analysis grounded in + German healthcare regulation (Sections~\ref{sec:threat} and~\ref{sec:security}). + \item A transport-agnostic design that operates over QUIC, TCP, and LoRa + mesh links (Section~\ref{sec:transport}). + \item An open-source reference implementation in Rust with 222~passing + tests, including 31~FAPP-specific integration tests. +\end{enumerate} + +% =========================================================================== +\section{Related Work} +\label{sec:related} +% =========================================================================== + +\paragraph{Centralized appointment platforms.} +Doctolib~\cite{doctolib2024} is the dominant commercial appointment platform +in Germany and France, offering real-time booking for physicians including +some psychotherapists. The KV's 116117 Terminservicestelle~\cite{terminservice116117} +provides telephone and online appointment referral mandated by +SGB~V~\S~75. Both systems are centralized: they require therapists to +register, maintain a server-side database of slots, and---critically---record +patient search queries, creating a correlation between identity and mental +health need. FAPP differs fundamentally by eliminating the central database and +enabling anonymous discovery. + +\paragraph{Decentralized healthcare data systems.} +Research on patient-controlled health records~\cite{mandl2007indivo} has +explored decentralized architectures where patients hold their own data. +Content-addressed storage systems like IPFS~\cite{benet2014ipfs} have been +proposed for medical record sharing. However, these focus on record +\emph{storage} rather than real-time \emph{service discovery}, and none +address the specific problem of appointment slot propagation in a +privacy-preserving manner. + +\paragraph{Mesh networking for constrained environments.} +Meshtastic~\cite{meshtastic2023} provides LoRa-based mesh networking for +text messaging with basic encryption. Reticulum~\cite{reticulum2023} +offers a cryptographic networking stack supporting multiple transport +layers including LoRa, with a focus on resilience. Briar~\cite{briar2017} +implements delay-tolerant, peer-to-peer messaging with Tor integration for +censorship resistance. FAPP draws architectural inspiration from these +systems---particularly Reticulum's transport abstraction and Briar's +store-and-forward model---but adds domain-specific semantics for appointment +discovery, structured query matching, and a therapist verification framework +absent from general-purpose mesh protocols. + +\paragraph{Privacy-preserving discovery.} +Anonymous communication systems, from onion routing~\cite{goldschlag1996onion} +to Mixminion~\cite{danezis2003mixminion}, provide sender anonymity at the +network layer. Off-the-Record messaging~\cite{borisov2004offrecord} achieves +deniability and forward secrecy in point-to-point communication. +MLS~\cite{rfc9420} extends these properties to group settings. FAPP's +privacy model is narrower but operationally distinct: rather than hiding +\emph{all} participants, it deliberately exposes therapist identity (as +required by professional regulation) while protecting patient anonymity. +This asymmetric model, while simpler than full anonymity systems, aligns +precisely with the regulatory and social requirements of psychotherapy +access. + +% =========================================================================== +\section{Threat Model and Privacy Requirements} +\label{sec:threat} +% =========================================================================== + +\subsection{Asymmetric Privacy Model} + +FAPP's privacy model reflects the inherent asymmetry of the +therapist--patient relationship in German healthcare law: + +\begin{description}[nosep,leftmargin=1.5em] + \item[Therapist identity is public.] Psychotherapists in Germany hold an + \emph{Approbation} (professional license) issued by the state health + authority. Their practice is listed in KV registries. FAPP + binds each therapist's mesh identity to their Approbation via a + SHA-256 hash of the credential number, creating accountability + without exposing the raw number to the mesh. + + \item[Patient queries are anonymous.] A \texttt{SlotQuery} message + contains only search filters (specialization, insurance type, postal + code prefix, time range) and a random correlation ID. No patient + identity, device fingerprint, or return address is attached. + Only when a patient \emph{chooses} to reserve a slot does an encrypted + channel to the therapist emerge. +\end{description} + +\subsection{Adversary Model} + +We consider the following adversary capabilities: + +\begin{enumerate}[nosep] + \item \textbf{Passive network observer.} An adversary who can observe all + mesh traffic on links they control. They can see message sizes, timing, + and CBOR-encoded (but not encrypted) FAPP frames for \texttt{SlotAnnounce} + and \texttt{SlotQuery} messages. They cannot observe the content of + \texttt{SlotReserve} or \texttt{SlotConfirm} payloads, which are + end-to-end encrypted. + + \item \textbf{Malicious relay node.} A relay node with \texttt{CAP\_FAPP\_RELAY} + that faithfully participates in message propagation but attempts to + correlate queries with reservations or de-anonymize patients. + + \item \textbf{Fake therapist.} An adversary who generates an Ed25519 keypair + and publishes \texttt{SlotAnnounce} messages with fabricated Approbation + hashes, attempting to collect patient contact data. + + \item \textbf{Denial-of-service attacker.} An adversary who floods the mesh + with spurious \texttt{SlotAnnounce} or \texttt{SlotQuery} messages to + exhaust relay storage or bandwidth. +\end{enumerate} + +We explicitly exclude the following from our threat model: +\begin{itemize}[nosep] + \item Global passive adversaries who observe all mesh links simultaneously. + \item Adversaries who compromise a therapist's long-term Ed25519 private key. + \item Physical-layer attacks on LoRa radio (jamming, direction finding). +\end{itemize} + +\subsection{Legal Context} + +The protocol operates within the German healthcare regulatory framework: + +\begin{itemize}[nosep] + \item \textbf{Approbation} (PsychThG \S~1): Psychotherapists require a + state-issued license. FAPP's therapist verification levels are designed + to interoperate with this credential system. + \item \textbf{Bedarfsplanung} (SGB~V \S~101): Regional capacity planning + determines the number of licensed therapy seats per area. FAPP does + not circumvent this system; it improves the visibility of slots within + it. + \item \textbf{Patient data protection} (GDPR, BDSG): Patient search behavior + constitutes health-related personal data under GDPR Art.~9. + FAPP's anonymous query design avoids generating this data category + entirely---a property no centralized platform can offer. + \item \textbf{Fernbehandlung} (MBO-{\"A} \S~7): Telemedicine regulations + require an initial in-person contact for some therapy modalities. + FAPP's \texttt{Modalitaet} field distinguishes in-person, video, and + hybrid sessions, supporting compliance-aware search. +\end{itemize} + +% =========================================================================== +\section{Protocol Design} +\label{sec:protocol} +% =========================================================================== + +\subsection{Overview} + +FAPP defines five message types that together implement a complete +appointment discovery and reservation lifecycle: + +\begin{enumerate}[nosep] + \item \textbf{SlotAnnounce}: Therapist publishes available time slots. + \item \textbf{SlotQuery}: Patient searches for matching slots (anonymous). + \item \textbf{SlotResponse}: Relay or therapist returns matching results. + \item \textbf{SlotReserve}: Patient claims a slot (E2E encrypted to therapist). + \item \textbf{SlotConfirm}: Therapist confirms or rejects the reservation. +\end{enumerate} + +\noindent The first three messages are \emph{cleartext} within the mesh (though +protected by transport-layer encryption on each hop). The last two carry +end-to-end encrypted payloads that intermediary nodes cannot read. + +\subsection{Capability Flags} + +FAPP extends the mesh announce protocol's capability bitfield with three +flags that allow nodes to declare their role: + +\begin{center} +\begin{tabular}{llp{7cm}} +\toprule +\textbf{Flag} & \textbf{Value} & \textbf{Semantics} \\ +\midrule +\texttt{CAP\_FAPP\_THERAPIST} & \texttt{0x0100} & Node is a licensed + therapist that publishes \texttt{SlotAnnounce} messages. \\ +\texttt{CAP\_FAPP\_RELAY} & \texttt{0x0200} & Node caches + \texttt{SlotAnnounce}s and answers \texttt{SlotQuery} messages from + its local store. \\ +\texttt{CAP\_FAPP\_PATIENT} & \texttt{0x0400} & Node can issue anonymous + \texttt{SlotQuery} and \texttt{SlotReserve} messages. \\ +\bottomrule +\end{tabular} +\end{center} + +\noindent A single node may combine flags---for example, a relay operated by +a patient advocacy group would set both \texttt{CAP\_FAPP\_RELAY} and +\texttt{CAP\_FAPP\_PATIENT}. + +\subsection{Message Specifications} + +\subsubsection{SlotAnnounce} + +A \texttt{SlotAnnounce} carries the therapist's available time slots +along with metadata needed for discovery and verification. Its fields +are: + +\begin{itemize}[nosep] + \item \texttt{id}: 16-byte unique identifier, derived as + $\texttt{SHA-256}(\texttt{therapist\_address} \| \texttt{sequence})[0..16]$. + \item \texttt{therapist\_address}: 16-byte truncated mesh address, + computed as $\texttt{SHA-256}(\texttt{Ed25519\_pubkey})[0..16]$. + \item \texttt{fachrichtung}: List of therapy specializations + (\emph{Verhaltenstherapie}, \emph{Tiefenpsychologisch fundiert}, + \emph{Analytisch}, \emph{Systemisch}, \emph{Kinder-/Jugend}). + \item \texttt{modalitaet}: Session modalities + (\emph{Praxis}, \emph{Video}, \emph{Hybrid}). + \item \texttt{kostentraeger}: Accepted insurance types + (\emph{GKV}, \emph{PKV}, \emph{Selbstzahler}). + \item \texttt{location\_hint}: Postal code (PLZ) only; never an exact address. + \item \texttt{slots}: Vector of \texttt{TimeSlot} records, each containing + \texttt{start\_unix} (Unix seconds), \texttt{duration\_minutes} (typically + 50 or 25), and \texttt{slot\_type} (\emph{Erstgespräch}, + \emph{Probatorik}, \emph{Therapie}, \emph{Akut}). + \item \texttt{approbation\_hash}: SHA-256 of the therapist's Approbation + number, binding the mesh identity to a real-world credential. + \item \texttt{profile\_url}: Optional URL to the therapist's public profile + (practice website, Jameda, KBV listing) for out-of-band verification. + \item \texttt{sequence}: Monotonically increasing counter per therapist, + used for deduplication and supersession of older announcements. + \item \texttt{ttl\_hours}: Time-to-live (default: 168 hours = 7 days). + \item \texttt{timestamp}: Unix seconds at creation. + \item \texttt{signature}: Ed25519 signature over all fields except + \texttt{signature} and \texttt{hop\_count}. + \item \texttt{hop\_count}, \texttt{max\_hops}: Current and maximum + propagation depth (default max: 8 hops). +\end{itemize} + +The signature covers a deterministic byte serialization of all non-excluded +fields, using fixed-width enum indices and \texttt{0xFF} separators between +variable-length sections. Forwarding nodes increment \texttt{hop\_count} +without re-signing---a design shared with the underlying mesh announce +protocol. + +\subsubsection{SlotQuery} + +A \texttt{SlotQuery} enables patients to search for available slots without +revealing their identity: + +\begin{itemize}[nosep] + \item \texttt{query\_id}: 16 random bytes for response correlation. + \item \texttt{fachrichtung}, \texttt{modalitaet}, \texttt{kostentraeger}: + Optional filters narrowing search results. + \item \texttt{plz\_prefix}: Optional postal code prefix (e.g., + \texttt{"80"} for the Munich area), enabling geographic filtering + without revealing the patient's exact location. + \item \texttt{earliest}, \texttt{latest}: Optional Unix-second bounds + on acceptable appointment times. + \item \texttt{slot\_type}: Optional filter by appointment type. + \item \texttt{max\_results}: Maximum number of results requested. +\end{itemize} + +\noindent No patient address, key, or identity material appears in the query. +The \texttt{query\_id} is random and single-use, providing no linkability +across queries. + +\subsubsection{SlotResponse} + +A \texttt{SlotResponse} contains the \texttt{query\_id} from the +originating query and a vector of matching \texttt{SlotAnnounce} records. +Full announce records are included so the patient can independently verify +each therapist's Ed25519 signature and Approbation hash binding. + +\subsubsection{SlotReserve} +\label{sec:reserve} + +When a patient selects a slot, they construct a \texttt{SlotReserve} +message containing: + +\begin{itemize}[nosep] + \item \texttt{slot\_announce\_id}: Reference to the target + \texttt{SlotAnnounce}. + \item \texttt{slot\_index}: Index into the announce's slot vector. + \item \texttt{patient\_ephemeral\_key}: A fresh X25519 public key + generated for this reservation. + \item \texttt{encrypted\_contact}: Patient contact information, encrypted + to the therapist's X25519 public key (derived from their Ed25519 + identity via standard birational mapping). +\end{itemize} + +\noindent The encryption scheme is detailed in Section~\ref{sec:crypto}. + +\subsubsection{SlotConfirm} + +The therapist's response contains: + +\begin{itemize}[nosep] + \item \texttt{slot\_announce\_id}, \texttt{slot\_index}: Identifies the + reserved slot. + \item \texttt{confirmed}: Boolean acceptance or rejection. + \item \texttt{encrypted\_details}: Appointment details (room, address, + instructions), encrypted to the patient's ephemeral key. + \item \texttt{therapist\_ephemeral\_key}: A fresh X25519 key generated for + this confirmation, providing forward secrecy. +\end{itemize} + +\subsection{Cryptographic Construction} +\label{sec:crypto} + +The E2E encryption for \texttt{SlotReserve} and \texttt{SlotConfirm} +follows a standard ECDH + KDF + AEAD pattern: + +\paragraph{Key agreement.} +The patient generates an ephemeral X25519 keypair +$(sk_P, pk_P)$~\cite{rfc7748}. The therapist's X25519 public key $pk_T$ +is derived from their Ed25519 identity key via the standard birational map. +The shared secret is computed as: +\[ + ss = \text{X25519}(sk_P, pk_T) +\] + +\paragraph{Key derivation.} +A 32-byte symmetric key is derived using HKDF-SHA256~\cite{rfc5869,hkdf2010krawczyk}: +\[ + k = \text{HKDF-Expand}(ss, \texttt{"fapp-reserve-v1"}, 32) +\] +For confirmations, the context string is \texttt{"fapp-confirm-v1"} and +the therapist generates a fresh ephemeral keypair, ensuring forward +secrecy even if the therapist's long-term key is later compromised. + +\paragraph{Authenticated encryption.} +Plaintext is encrypted with ChaCha20-Poly1305~\cite{rfc8439,bernstein2012chacha} +using a random 12-byte nonce. The ciphertext format is: +\[ + \texttt{nonce}_{12} \| \texttt{ciphertext} \| \texttt{tag}_{16} +\] +This construction provides IND-CCA2 security under standard assumptions. + +\subsection{Wire Format} + +All FAPP messages are serialized with CBOR (Concise Binary Object +Representation, RFC~8949~\cite{rfc8949}), consistent with the \qpq{} +mesh envelope and announce formats. On the wire, each FAPP frame is +prefixed with a single-byte tag identifying the message type: + +\begin{center} +\begin{tabular}{cl} +\toprule +\textbf{Tag} & \textbf{Message Type} \\ +\midrule +\texttt{0x01} & \texttt{SlotAnnounce} \\ +\texttt{0x02} & \texttt{SlotQuery} \\ +\texttt{0x03} & \texttt{SlotResponse} \\ +\texttt{0x04} & \texttt{SlotReserve} \\ +\texttt{0x05} & \texttt{SlotConfirm} \\ +\bottomrule +\end{tabular} +\end{center} + +\noindent CBOR was chosen over Protocol Buffers or JSON for three reasons: +(1)~self-describing format requiring no schema negotiation, (2)~compact +binary encoding suitable for LoRa's constrained bandwidth, and (3)~existing +use throughout the \qpq{} mesh stack, avoiding a second serialization +dependency. + +\subsection{Propagation Rules} + +\texttt{SlotAnnounce} messages propagate via controlled flooding: + +\begin{enumerate}[nosep] + \item A relay node receiving an announce checks \texttt{hop\_count} $<$ + \texttt{max\_hops} and \texttt{timestamp} + \texttt{ttl\_hours} $>$ + current time. Failing either check, the message is dropped. + \item The announce is deduplicated against a bounded set of seen IDs + (capacity: 50{,}000). Duplicate IDs are silently dropped. + \item Sequence-based supersession: if the relay has seen a higher + \texttt{sequence} from the same \texttt{therapist\_address}, the + incoming announce is rejected. + \item If the relay has the therapist's public key, the Ed25519 signature + is verified. Invalid signatures cause immediate rejection. + \item The announce is stored in the relay's \texttt{FappStore} (bounded + to 10{,}000 total entries and 50 per therapist) and re-broadcast with + \texttt{hop\_count} incremented. +\end{enumerate} + +\texttt{SlotQuery} messages propagate similarly but with shorter effective +TTLs. Relay nodes that hold matching \texttt{SlotAnnounce} records in +their local store respond directly, reducing query propagation depth. + +% =========================================================================== +\section{Mesh Transport Integration} +\label{sec:transport} +% =========================================================================== + +FAPP is transport-agnostic by design. It produces and consumes byte +frames; the underlying \qpq{} mesh stack handles routing, fragmentation, +and transport selection. + +\subsection{Transport Layer Architecture} + +The \qpq{} mesh provides three transport backends through a unified +\texttt{TransportManager} abstraction: + +\begin{description}[nosep,leftmargin=1.5em] + \item[QUIC (primary).] QUIC over UDP~\cite{rfc9000} with TLS~1.3 mutual + authentication. Used for high-bandwidth links between nodes with + internet connectivity. Each mesh connection uses the ALPN identifier + \texttt{quicprochat/mesh/1}. + + \item[TCP (fallback).] Length-prefixed TCP streams for environments where + UDP is blocked or NAT traversal fails. Provides reliable, ordered + delivery at the cost of head-of-line blocking. + + \item[LoRa (constrained).] Sub-GHz radio links using LoRa modulation + (EU868 band)~\cite{lora2015semtech} for infrastructure-independent + operation. Subject to ETSI EN~300~220 duty cycle limits (1\% in the + 868.0--868.6~MHz sub-band)~\cite{eu868dutycycle}. +\end{description} + +\noindent The \texttt{TransportManager} selects the transport based on the +destination address type and provides automatic capability classification +(Unconstrained, Medium, Constrained, Severely\-Constrained) that influences +cryptographic mode selection. + +\subsection{Hop-Based Propagation} + +FAPP messages propagate through the mesh as payloads inside +\texttt{Mesh\-Envelope} containers. Each envelope carries: + +\begin{itemize}[nosep] + \item Source and destination 16-byte truncated addresses. + \item TTL counter decremented at each hop. + \item Ed25519 signature (for authenticity, not confidentiality). + \item Nonce for replay detection. +\end{itemize} + +\noindent The mesh router maintains a \texttt{RoutingTable} with entries +learned from periodic \texttt{MeshAnnounce} messages. For FAPP's flooding +pattern, outbound frames are sent to all known next-hop addresses +(\emph{flood fan-out}). + +\subsection{Deduplication and Store-and-Forward} + +Deduplication operates at two levels: + +\begin{enumerate}[nosep] + \item \textbf{Envelope level.} The mesh router tracks seen envelope nonces + in a bounded set, preventing the same envelope from being forwarded + twice. + \item \textbf{FAPP level.} The \texttt{FappStore} tracks seen announce IDs + (bounded to 50{,}000 entries with FIFO eviction) and per-therapist + sequence numbers. An announce with a sequence number lower than the + last seen value for that therapist is rejected immediately. +\end{enumerate} + +\noindent Store-and-forward is handled by the \texttt{MeshStore}, which queues +messages for offline recipients and delivers them upon reconnection. This +is particularly relevant for therapist nodes that may only be online during +practice hours. + +\subsection{Location Hints and PLZ-Based Filtering} + +FAPP uses German postal codes (PLZ) as coarse location hints. The +five-digit PLZ system provides geographic granularity at the city or +district level without revealing exact addresses. Query-time filtering +on PLZ prefixes allows geographic scoping: + +\begin{itemize}[nosep] + \item \texttt{"8"}: all of Bavaria and parts of Baden-Württemberg. + \item \texttt{"80"}: Munich metropolitan area. + \item \texttt{"803"}: central Munich districts. +\end{itemize} + +\noindent This prefix-based approach lets patients control the trade-off between +geographic precision and result volume without disclosing their own +location. + +\subsection{LoRa Considerations} + +LoRa links impose severe bandwidth constraints. At SF12/BW125 (the +most resilient configuration), the effective payload per frame is +approximately 51 bytes~\cite{lora2015semtech}. Measured FAPP message +sizes in the reference implementation are: + +\begin{center} +\begin{tabular}{lrl} +\toprule +\textbf{Message} & \textbf{CBOR Size} & \textbf{SF12 Fragments} \\ +\midrule +\texttt{SlotAnnounce} (2 slots) & $\sim$320 bytes & 7 \\ +\texttt{SlotQuery} (all filters) & $\sim$90 bytes & 2 \\ +\texttt{SlotReserve} & $\sim$110 bytes & 3 \\ +\texttt{SlotConfirm} & $\sim$100 bytes & 2 \\ +\bottomrule +\end{tabular} +\end{center} + +\noindent The \qpq{} LoRa transport handles fragmentation and reassembly +transparently, with a \texttt{DutyCycleTracker} enforcing EU868 1\% +duty cycle compliance. At SF12, transmitting a full \texttt{SlotAnnounce} +takes approximately 14 seconds of airtime, consuming roughly 0.4\% of the +hourly duty budget. This is viable for low-frequency announcements but +precludes real-time query--response interactions over LoRa alone. +A practical deployment would use LoRa for announce propagation in +areas without internet connectivity, with queries flowing over +QUIC or TCP where available. + +% =========================================================================== +\section{Security Analysis} +\label{sec:security} +% =========================================================================== + +\subsection{Patient Anonymity} + +\texttt{SlotQuery} messages contain no patient-identifying information: +no return address, no public key, no device fingerprint. The +\texttt{query\_id} is a random 16-byte value generated per query, +providing no cross-query linkability. + +\emph{Limitation:} In the current design, a relay node can observe +\emph{which incoming link} a query arrived on, potentially correlating +it with a directly connected patient node. Mitigations include +multi-hop query forwarding (where intermediate nodes strip source +information) and cover traffic. The return path for responses is +discussed as future work in Section~\ref{sec:future}. + +\subsection{Therapist Verification} +\label{sec:verification} + +FAPP provides three verification levels for therapist identity: + +\begin{description}[nosep,leftmargin=1.5em] + \item[Level 0: Mesh signature only.] + The therapist's \texttt{SlotAnnounce} is signed with their Ed25519 key. + This proves control of the corresponding mesh identity but does not bind + it to a real-world person. The \texttt{approbation\_hash} field + (SHA-256 of the Approbation number) creates a commitment but is not + independently verifiable at this level, since an attacker could + fabricate a hash. + + \item[Level 1: Endorsement by trusted relays.] + Trusted relay nodes---operated, for example, by patient advocacy + organizations (\emph{Unabhängige Patientenberatung})---can sign + \texttt{Endorsement} records attesting to a therapist's identity after + out-of-band verification. This creates a web-of-trust model where + patients can filter by endorser reputation. + + \item[Level 2: Registry verification.] + A gateway node queries the KBV physician registry using the therapist's + \emph{Lebenslange Arztnummer} (LANR) and signs an attestation binding + the mesh identity to the registry entry. This provides the highest + assurance but requires infrastructure for registry access. +\end{description} + +\noindent The current reference implementation operates at Level~0 with +a \texttt{profile\_url} field enabling manual cross-verification. The +client UI displays prominent warnings for unverified therapists. + +\subsection{Denial of Service} + +FAPP employs several mechanisms to resist denial-of-service attacks: + +\begin{enumerate}[nosep] + \item \textbf{Rate limiting.} Relay nodes enforce a maximum of 10 + \texttt{SlotAnnounce} messages per hour per \texttt{therapist\_address} + using a sliding-window rate limiter. + + \item \textbf{Capacity bounds.} The \texttt{FappStore} limits total + cached announcements to 10{,}000 and per-therapist announcements to 50, + with oldest-first eviction. + + \item \textbf{Hop limits.} The \texttt{max\_hops} field (default: 8) + bounds propagation depth, preventing amplification attacks. + + \item \textbf{TTL enforcement.} Expired announcements (\texttt{timestamp} + + \texttt{ttl\_hours} $\times$ 3600 < current time) are dropped on + receipt and garbage-collected from stores periodically. + + \item \textbf{Backpressure.} The mesh layer's \texttt{BackpressureController} + implements priority-based load shedding, preferring to drop low-priority + traffic (queries from unknown peers) before high-priority traffic + (announces from verified therapists). +\end{enumerate} + +\subsection{Sybil Resistance} +\label{sec:sybil} + +The Sybil attack~\cite{douceur2002sybil}---where an adversary creates +many pseudonymous identities---is a concern for FAPP in two contexts: + +\begin{description}[nosep,leftmargin=1.5em] + \item[Fake therapists.] An attacker generates multiple Ed25519 keypairs + and publishes \texttt{SlotAnnounce} messages from each. + \emph{Mitigation:} The \texttt{approbation\_hash} field forces the + attacker to commit to a credential number per identity. While + fabricating hashes is trivial, each fabricated identity is + independently rate-limited and consumes the attacker's store + budget. Level~1 and Level~2 verification (Section~\ref{sec:verification}) + provide progressively stronger Sybil resistance by requiring + out-of-band identity binding. + + \item[Fake relay nodes.] An attacker operates many relay nodes to + observe traffic patterns. + \emph{Mitigation:} FAPP's flooding model means all relays see + approximately the same traffic; additional Sybil relays gain no + information advantage beyond what a single relay provides. For + point-to-point messages (\texttt{SlotReserve}, \texttt{SlotConfirm}), + E2E encryption ensures that even colluding relays cannot read + content. +\end{description} + +\subsection{Slot Squatting} + +An adversary could attempt to reserve all announced slots to deny +service to legitimate patients. Since \texttt{SlotReserve} messages are +E2E encrypted, the therapist must decrypt and process each reservation +individually. Mitigations include: + +\begin{itemize}[nosep] + \item Therapists can reject suspicious reservations via + \texttt{SlotConfirm} with \texttt{confirmed = false}. + \item Rate limiting on \texttt{SlotReserve} per therapist (enforced at + the therapist node). + \item The patient must provide genuine contact information (encrypted) + for the reservation to be actionable; a therapist who cannot reach the + patient can cancel and re-announce the slot. +\end{itemize} + +\subsection{Replay Protection} + +Replay attacks are mitigated at two levels: + +\begin{enumerate}[nosep] + \item \textbf{Announce deduplication.} The \texttt{(therapist\_address, + sequence)} pair uniquely identifies each announce version. A replayed + announce with a sequence number already seen or lower than the latest is + rejected. + \item \textbf{Envelope nonces.} The mesh envelope layer uses random nonces + tracked in a bounded seen-set, preventing replay of the transport + container. + \item \textbf{TTL expiry.} Even if a dedup cache is evicted, the + \texttt{timestamp} + \texttt{ttl\_hours} check prevents acceptance of + stale announces. +\end{enumerate} + +% =========================================================================== +\section{Discussion} +\label{sec:discussion} +% =========================================================================== + +\subsection{Comparison with Centralized Alternatives} + +\begin{table}[t] +\centering +\caption{Comparison of psychotherapy appointment systems.} +\label{tab:comparison} +\begin{tabularx}{\textwidth}{lccccX} +\toprule +& \textbf{Real-time} & \textbf{Patient} & \textbf{Decen-} & + \textbf{Verifi-} & \\ +\textbf{System} & \textbf{slots} & \textbf{anon.} & \textbf{tralized} & + \textbf{cation} & \textbf{Notes} \\ +\midrule +116117~\cite{terminservice116117} & Partial & No & No & Official & + Telephone/web; limited slot data; identity required for referral. \\ +Doctolib~\cite{doctolib2024} & Yes & No & No & Self-report & + Tracks search behavior; therapist opt-in required; commercial fees. \\ +KBV Arztsuche~\cite{kbvarztsuche} & No & Partial & No & Official & + Practice info only; no real-time availability. \\ +FAPP (Level~0) & Yes & Yes & Yes & Mesh sig. & + Anonymous search; no infrastructure; limited identity assurance. \\ +FAPP (Level~2) & Yes & Yes & Yes & Registry & + Requires trusted gateway; strongest guarantees. \\ +\bottomrule +\end{tabularx} +\end{table} + +Table~\ref{tab:comparison} summarizes the trade-offs. FAPP is the only system +that offers both real-time slot visibility and patient anonymity. This +comes at the cost of weaker therapist verification at Level~0, which is +an explicit design trade-off: we prioritize patient privacy and system +availability over centralized credential checking, with a planned +upgrade path to registry-backed verification. + +\subsection{Deployment Challenges} + +\paragraph{Therapist adoption.} +FAPP requires therapists to run mesh node software and actively manage +their slot announcements. While the protocol is designed for automation +(a background daemon can publish slots from the practice management +system), adoption depends on therapists perceiving the system as +lower-friction than existing alternatives. Integration with established +PVS (Praxisverwaltungssoftware) systems is essential for adoption. + +\paragraph{Network bootstrapping.} +A mesh network requires a critical mass of relay nodes to provide +adequate coverage. Initial deployment can leverage existing \qpq{} +infrastructure (the messenger's server-to-server federation provides +seed connectivity), but sustained operation benefits from dedicated +relay nodes at healthcare institutions, patient advocacy organizations, +or community networks. + +\paragraph{Key management.} +Therapists must protect their Ed25519 private key, which serves as +both their mesh identity and the anchor for their professional +reputation. Key compromise requires generating a new identity and +re-establishing verification, analogous to certificate revocation in +PKI systems. The \qpq{} key transparency module provides Merkle-log +based revocation, but its integration with FAPP is ongoing work. + +\subsection{Regulatory Considerations} + +FAPP does not replace or circumvent the KV's appointment allocation +system. It operates as a complementary discovery layer: therapists +who have unfilled slots can announce them through the mesh in addition +to reporting them through official channels. Since FAPP does not +handle billing, prescriptions, or clinical data, it falls outside the +scope of Telematikinfrastruktur (TI) certification requirements. + +Patient anonymity aligns with GDPR's data minimization principle +(Art.~5(1)(c)): by not collecting or processing patient identity data +during the search phase, FAPP avoids creating the health-related personal +data that centralized platforms inevitably generate. + +\subsection{LoRa Constraints and Hybrid Deployment} + +Pure LoRa deployment is impractical for interactive query--response +patterns due to duty cycle constraints and high latency. A realistic +deployment uses LoRa for \emph{announce propagation} in connectivity +gaps (rural areas, community mesh networks) while routing queries +and reservations over internet-connected transports. The \qpq{} +\texttt{TransportManager} handles this routing transparently: +a relay node connected to both LoRa and TCP will bridge announces +between networks without application-layer awareness. + +% =========================================================================== +\section{Conclusion and Future Work} +\label{sec:future} +% =========================================================================== + +FAPP demonstrates that privacy-preserving appointment discovery is +achievable in a decentralized architecture without sacrificing the +verifiability requirements of a regulated healthcare profession. +The asymmetric privacy model---public therapist, anonymous patient---is +not merely a technical design choice but a reflection of the social +contract underlying psychotherapy: the professional is accountable, +the patient is protected. + +The reference implementation in Rust, comprising approximately 1{,}600 +lines of protocol code with 31 dedicated tests and full E2E encryption +support, validates the design's feasibility. CBOR serialization keeps +message sizes within LoRa fragmentation budgets, and the integration +with \qpq{}'s multi-transport mesh stack demonstrates that +a single protocol can operate across QUIC, TCP, and radio links. + +Several directions remain for future work: + +\paragraph{Anonymous return paths.} +The current design lacks a robust mechanism for routing +\texttt{SlotResponse} messages back to anonymous query originators. +The \texttt{SlotQuery} specification includes a \texttt{return\_path} +field for onion-style routing~\cite{goldschlag1996onion}, where each +hop in the return path is encrypted to the respective relay's key, +but this is not yet implemented. Realizing this would provide +Mixminion-style~\cite{danezis2003mixminion} unlinkability between +queries and their originators. + +\paragraph{Multi-hop privacy for reservations.} +\texttt{SlotReserve} messages are currently E2E encrypted but routed +by flooding, which reveals the approximate network location of the +originator to neighboring nodes. A circuit-based routing scheme, +where the patient establishes a multi-hop tunnel before sending the +reservation, would provide stronger traffic analysis resistance. + +\paragraph{E2E encrypted channels.} +After a successful reservation, the therapist and patient could +establish a persistent MLS~\cite{rfc9420} session through the mesh +for ongoing communication (appointment changes, intake forms). +The \qpq{} stack already supports MLS group key agreement; bridging +FAPP's ephemeral key exchange to a durable MLS session is a natural +extension. + +\paragraph{Endorsement gossip protocol.} +Level~1 verification (Section~\ref{sec:verification}) requires a gossip +protocol for distributing and aggregating endorsements from trusted +relays. This protocol must resist endorsement inflation (where +colluding nodes endorse each other) while remaining lightweight +enough for constrained transports. + +\paragraph{Real-world pilot.} +We plan a pilot deployment in a German metropolitan area, partnering +with a small group of psychotherapists willing to announce slots +through the mesh alongside their existing booking channels. The +pilot will measure (a)~slot discovery latency, (b)~relay network +coverage requirements, and (c)~therapist and patient usability +perceptions. Lessons from this pilot will inform protocol revisions +and inform regulatory engagement with the relevant KV. + +\paragraph{Post-quantum key exchange.} +The \qpq{} mesh stack supports a hybrid X25519 + ML-KEM-768 key +encapsulation mechanism at the envelope level. Integrating post-quantum +key exchange into FAPP's reservation encryption would future-proof +patient contact data against quantum adversaries, though the increased +message sizes (approximately 2{,}676 bytes for a PQ-hybrid KeyPackage +versus 306 bytes for classical) make this impractical on LoRa links +with current duty cycle budgets. + +\bigskip +\noindent The source code, protocol specification, and integration tests +are available at the \qpq{} project repository under the MIT license. + +\bibliographystyle{plain} +\bibliography{fapp-refs} + +\end{document}