Add the Calendula and Agendula privacy policies #7
@@ -7,7 +7,7 @@ const year = new Date().getFullYear();
|
|||||||
<footer class="site-footer">
|
<footer class="site-footer">
|
||||||
<div class="site-footer__inner">
|
<div class="site-footer__inner">
|
||||||
<p>
|
<p>
|
||||||
© {year} {SITE.author} · <a href="/uses">Uses</a> ·
|
© {year} {SITE.author} · <a href="/uses">Uses</a> ·{' '}
|
||||||
<a href="/impressum">Impressum</a> · <a href="/datenschutz">Datenschutz</a>
|
<a href="/impressum">Impressum</a> · <a href="/datenschutz">Datenschutz</a>
|
||||||
</p>
|
</p>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,328 @@
|
|||||||
|
---
|
||||||
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||||
|
import { LEGAL } from '../../consts';
|
||||||
|
|
||||||
|
// App privacy policy for Agendula — required as a public URL by the Google Play
|
||||||
|
// Console (mandatory for every app) and linked from the app's About card.
|
||||||
|
// Deliberately separate from /datenschutz, which covers this website only.
|
||||||
|
//
|
||||||
|
// Kept in English because SITE.lang is 'en' and Play's default store listing is
|
||||||
|
// en-US; /datenschutz and /impressum stay German for legal reasons.
|
||||||
|
//
|
||||||
|
// Source of truth for the facts below: the Agendula repository (docs/PRIVACY.md,
|
||||||
|
// docs/SYNC.md, AndroidManifest.xml, backup_rules.xml). Unlike Calendula,
|
||||||
|
// Agendula *does* hold INTERNET — it has its own CalDAV sync — so the wording
|
||||||
|
// here turns on "only to the server you entered", not on the absence of the
|
||||||
|
// permission. If sync, permissions or data paths change, update this page and
|
||||||
|
// the "Last updated" date.
|
||||||
|
const lastUpdated = '9 September 2026';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Agendula — Privacy Policy"
|
||||||
|
description="Privacy policy for the Agendula Android task app. No accounts, no analytics, no tracking — data leaves your device only for the CalDAV server you choose."
|
||||||
|
width="narrow"
|
||||||
|
>
|
||||||
|
<article class="prose">
|
||||||
|
<h1 class="page-title">Privacy Policy — Agendula</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Last updated:</strong> {lastUpdated}<br />
|
||||||
|
Applies to the Android app <strong>Agendula</strong>{' '}
|
||||||
|
(package <code>de.jeanlucmakiola.agendula</code>), all versions and all
|
||||||
|
distribution channels.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>In short</h2>
|
||||||
|
<p>
|
||||||
|
Agendula has no servers, no user accounts and no analytics. Your tasks live
|
||||||
|
on your device. They leave it in exactly one case: if you set up a CalDAV
|
||||||
|
account yourself, they are synchronised with <strong>the server you
|
||||||
|
entered</strong> — and with nothing and no one else. Nothing is ever sent
|
||||||
|
to the developer.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>1. Controller</h2>
|
||||||
|
<p>
|
||||||
|
{LEGAL.business}<br />
|
||||||
|
{LEGAL.street}<br />
|
||||||
|
{LEGAL.city}<br />
|
||||||
|
Email: <a href={`mailto:${LEGAL.email}`}>{LEGAL.email}</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>2. No data collection by the developer</h2>
|
||||||
|
<p>
|
||||||
|
Agendula contains <strong>no analytics, no tracking, no advertising, no
|
||||||
|
crash-reporting SDK and no third-party service that reports anything
|
||||||
|
anywhere</strong>. No user profile is created, no advertising or device
|
||||||
|
identifier is generated, and no data is shared with or sold to anyone.
|
||||||
|
There is no Agendula account, and the developer operates no server that the
|
||||||
|
app talks to.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
All of this is verifiable in the{' '}
|
||||||
|
<a href="https://codeberg.org/jlmakiola/agendula" rel="noopener">source code</a>,
|
||||||
|
which is public.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>3. Where your tasks live — your choice</h2>
|
||||||
|
<p>
|
||||||
|
Agendula offers two storage modes, and you pick one:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>On your device (the default)</strong> — your task lists, tasks and
|
||||||
|
reminders are kept in Agendula's own database inside the app's private
|
||||||
|
storage. Nothing is published to other apps, and uninstalling the app
|
||||||
|
removes it.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>In a tasks provider you already use</strong> — OpenTasks or
|
||||||
|
tasks.org. Agendula then reads and writes that app's task database
|
||||||
|
through Android's provider mechanism, after you grant its read/write
|
||||||
|
permission. Whatever already synchronises that provider (DAVx5,
|
||||||
|
SmoothSync, DecSync CC, …) keeps doing so, unchanged; that synchronisation
|
||||||
|
is performed by those apps, not by Agendula, and their privacy policies
|
||||||
|
apply to it.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>4. CalDAV sync — the only case where your tasks leave the device</h2>
|
||||||
|
<p>
|
||||||
|
Sync is optional and off until you add an account. If you add one,
|
||||||
|
everything below happens between your device and <strong>the server you
|
||||||
|
nominated</strong>, and nowhere else.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>What is stored on your device</h3>
|
||||||
|
<p>
|
||||||
|
The server address, your username, and your password or app password. The
|
||||||
|
password is encrypted with a key held in the Android Keystore, which cannot
|
||||||
|
be exported from the device.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>What is transmitted, and to whom</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
The tasks in the synchronised lists, as standard iCalendar
|
||||||
|
(<code>VTODO</code>) data, and the credentials needed to authenticate.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Requests carry the user agent <code>Agendula (Android)</code> — a fixed
|
||||||
|
string, so that you can recognise and revoke the session on your server.
|
||||||
|
No device identifier is sent.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Connections are HTTPS. Cleartext HTTP is refused, so credentials are
|
||||||
|
never sent over an unencrypted connection.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Under Google Play's Data Safety definitions this counts as{' '}
|
||||||
|
<strong>collected</strong> — Play defines collection as transmitting data
|
||||||
|
off the device, regardless of who receives it — and <strong>not
|
||||||
|
shared</strong>, because the only recipient is the server you chose. Data is
|
||||||
|
encrypted in transit.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Finding your server</h3>
|
||||||
|
<p>
|
||||||
|
When you type a server address or an email domain, Agendula follows the
|
||||||
|
standard discovery procedure (RFC 6764): a DNS lookup for the{' '}
|
||||||
|
<code>_caldavs._tcp</code> service record of that domain, then{' '}
|
||||||
|
<code>/.well-known/caldav</code> on the host. The DNS query goes to whichever
|
||||||
|
resolver your device or network uses, and the requests go to the domain you
|
||||||
|
typed — no directory of servers is consulted and no lookup is sent to the
|
||||||
|
developer.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Signing in to a Nextcloud</h3>
|
||||||
|
<p>
|
||||||
|
If the server is a Nextcloud, Agendula uses Nextcloud's Login Flow v2: your
|
||||||
|
browser opens <em>your own server's</em> login page, you authorise there,
|
||||||
|
and the server hands the app a dedicated app password. Agendula never sees
|
||||||
|
your actual account password. The app password appears in your server's
|
||||||
|
“Devices & sessions” list as <code>Agendula (Android)</code>, and you can
|
||||||
|
revoke it there at any time. Removing the account in Agendula revokes it too,
|
||||||
|
where the server supports that.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Your server's own policy</h3>
|
||||||
|
<p>
|
||||||
|
Your CalDAV provider has its own privacy policy, and your data on their
|
||||||
|
server is governed by it. Agendula has no relationship with them.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
A note on certificates: Agendula trusts private certificate authorities that
|
||||||
|
you have installed in your device's user store, because self-hosted servers
|
||||||
|
routinely use them. That is a deliberate trade-off in favour of
|
||||||
|
self-hosters — any CA installed on your device (for example by an employer's
|
||||||
|
management profile) can, in principle, intercept traffic from the app, as it
|
||||||
|
can from other apps that make the same choice.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>5. Other data Agendula handles on your device</h2>
|
||||||
|
|
||||||
|
<h3>Reminders and notifications</h3>
|
||||||
|
<p>
|
||||||
|
Due-date reminders are scheduled by the app itself and displayed as local
|
||||||
|
notifications. Nothing is sent to a push service — there is no push service.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Export files</h3>
|
||||||
|
<p>
|
||||||
|
You can export your tasks as standard iCalendar <code>.ics</code> files.
|
||||||
|
Agendula writes exactly the file you select through Android's system file
|
||||||
|
picker, and has no access to other files.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>App settings</h3>
|
||||||
|
<p>
|
||||||
|
Your preferences (theme, language, list and reminder defaults and similar)
|
||||||
|
are stored locally on your device and are removed when you uninstall the
|
||||||
|
app.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>6. Backups</h2>
|
||||||
|
<p>
|
||||||
|
If Android Auto Backup is enabled on your device, your tasks and settings
|
||||||
|
may be backed up to your own Google account, under Google's terms — the
|
||||||
|
developer has no access to it. Two things are deliberately excluded from
|
||||||
|
that backup: your stored CalDAV password, and Agendula's per-device sync
|
||||||
|
bookkeeping. After restoring onto a new device you therefore sign in to your
|
||||||
|
server again.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>7. Crash reports</h2>
|
||||||
|
<p>
|
||||||
|
If Agendula crashes, it offers to report the problem. Nothing is sent
|
||||||
|
automatically, even though the app has network access. The report is copied
|
||||||
|
to your clipboard and your browser is opened with the project's issue
|
||||||
|
tracker, the text pre-filled. <strong>You see the full content, you decide
|
||||||
|
whether to submit it, and you can edit or discard it.</strong>
|
||||||
|
</p>
|
||||||
|
<p>Such a report contains:</p>
|
||||||
|
<ul>
|
||||||
|
<li>app version,</li>
|
||||||
|
<li>Android version,</li>
|
||||||
|
<li>device manufacturer and model,</li>
|
||||||
|
<li>your device language,</li>
|
||||||
|
<li>the timestamp,</li>
|
||||||
|
<li>and the technical stack trace.</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
It is built from that fixed list and nothing else: <strong>no</strong> task
|
||||||
|
data, <strong>no</strong> server address or credentials, <strong>no</strong>{' '}
|
||||||
|
account names, <strong>no</strong> log files and <strong>no</strong> personal
|
||||||
|
identifiers.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you choose to submit it, the report becomes a public issue on the
|
||||||
|
project's issue tracker at Codeberg, operated by Codeberg e. V.
|
||||||
|
Their privacy policy then applies to that submission.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>8. External links</h2>
|
||||||
|
<p>
|
||||||
|
The app links to the source code, the licence, the issue tracker, the
|
||||||
|
translation platform (Weblate) and a voluntary donation page (Ko-fi).
|
||||||
|
Following one of these links opens your browser and leaves the app; the
|
||||||
|
privacy policy of the respective website then applies. Agendula transmits no
|
||||||
|
data of yours in the process — it only opens the address.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>9. Permissions and why they exist</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>INTERNET</code>, <code>ACCESS_NETWORK_STATE</code> — CalDAV sync with
|
||||||
|
the server you configure, and checking whether a connection exists before
|
||||||
|
trying. Without a CalDAV account, no connection is made.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>READ_SYNC_SETTINGS</code>, <code>WRITE_SYNC_SETTINGS</code> — register
|
||||||
|
the sync account with Android's sync framework so it can be scheduled.
|
||||||
|
</li>
|
||||||
|
<li><code>POST_NOTIFICATIONS</code> — show reminders.</li>
|
||||||
|
<li>
|
||||||
|
<code>USE_EXACT_ALARM</code>, <code>SCHEDULE_EXACT_ALARM</code> — deliver
|
||||||
|
reminders at the exact due time.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>RECEIVE_BOOT_COMPLETED</code> — re-register pending reminders after a
|
||||||
|
restart.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>org.dmfs.permission.READ_TASKS</code> /{' '}
|
||||||
|
<code>WRITE_TASKS</code> and <code>org.tasks.permission.READ_TASKS</code> /{' '}
|
||||||
|
<code>WRITE_TASKS</code> — optional, requested only if you choose the
|
||||||
|
external-provider storage mode, and only for the provider you selected
|
||||||
|
(OpenTasks or tasks.org).
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>WAKE_LOCK</code>, <code>FOREGROUND_SERVICE</code> — required by the
|
||||||
|
Android system component used for scheduled background work
|
||||||
|
(WorkManager); on older Android versions it needs them to run an
|
||||||
|
expedited sync.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Agendula publishes no content provider of its own and declares no
|
||||||
|
permissions that other apps could request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>10. Distribution channels</h2>
|
||||||
|
<p>
|
||||||
|
Agendula is distributed via F-Droid, Obtainium, a self-hosted repository
|
||||||
|
and, where applicable, the Google Play Store. When you download or update
|
||||||
|
the app, the operator of that channel processes data (such as your IP
|
||||||
|
address) under their own privacy policy. This is outside the developer's
|
||||||
|
control and unrelated to the app's own behaviour.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>11. Children</h2>
|
||||||
|
<p>
|
||||||
|
Agendula is not directed at children and collects nothing about anyone.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>12. Deleting your data</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>Remove a CalDAV account</strong> (Settings → Accounts) deletes the
|
||||||
|
stored credential and, where the server supports it, revokes the app
|
||||||
|
password. The task lists become device-only lists rather than being
|
||||||
|
destroyed.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Remove an account and delete its local data</strong> removes those
|
||||||
|
lists and their tasks as well.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Uninstalling the app</strong> removes everything Agendula stored on
|
||||||
|
the device.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Data on your CalDAV server is deleted on that server; data in an external
|
||||||
|
tasks provider is deleted in that app.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>13. Your rights</h2>
|
||||||
|
<p>
|
||||||
|
The developer stores no personal data of yours — the only data transfer the
|
||||||
|
app performs is between your device and a server you operate or chose. There
|
||||||
|
is therefore no data held by the developer to which rights of access,
|
||||||
|
rectification, erasure, restriction, data portability or objection
|
||||||
|
(Art. 15–21 GDPR) could apply. Your tasks are exportable as standard{' '}
|
||||||
|
<code>.ics</code> files from within the app at any time. You may contact the
|
||||||
|
address above with any question, and you have the right to lodge a complaint
|
||||||
|
with a supervisory authority.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>14. Changes to this policy</h2>
|
||||||
|
<p>
|
||||||
|
Should the app's functionality change in a way that affects data processing,
|
||||||
|
this policy will be updated and the date at the top adjusted. The version
|
||||||
|
history is publicly traceable in the project's source repository.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
</BaseLayout>
|
||||||
@@ -26,7 +26,7 @@ const lastUpdated = '28 July 2026';
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
<strong>Last updated:</strong> {lastUpdated}<br />
|
<strong>Last updated:</strong> {lastUpdated}<br />
|
||||||
Applies to the Android app <strong>Calendula</strong>
|
Applies to the Android app <strong>Calendula</strong>{' '}
|
||||||
(package <code>de.jeanlucmakiola.calendula</code>), all versions and all
|
(package <code>de.jeanlucmakiola.calendula</code>), all versions and all
|
||||||
distribution channels.
|
distribution channels.
|
||||||
</p>
|
</p>
|
||||||
@@ -174,7 +174,7 @@ const lastUpdated = '28 July 2026';
|
|||||||
system dialog for the “Reliable delivery” setting.
|
system dialog for the “Reliable delivery” setting.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<code>WAKE_LOCK</code>, <code>FOREGROUND_SERVICE</code>, <code>ACCESS_NETWORK_STATE</code>
|
<code>WAKE_LOCK</code>, <code>FOREGROUND_SERVICE</code>, <code>ACCESS_NETWORK_STATE</code>{' '}
|
||||||
— required by the Android system component used for scheduled background
|
— required by the Android system component used for scheduled background
|
||||||
work (WorkManager).
|
work (WorkManager).
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { LEGAL } from '../consts';
|
|||||||
<article class="prose">
|
<article class="prose">
|
||||||
<h1 class="page-title">Uses</h1>
|
<h1 class="page-title">Uses</h1>
|
||||||
<p>
|
<p>
|
||||||
A running colophon of the tools and stack behind this site, the
|
A running colophon of the tools and stack behind this site, the{' '}
|
||||||
<a href="/work">Floret apps</a>, and the infrastructure they run on. The
|
<a href="/work">Floret apps</a>, and the infrastructure they run on. The
|
||||||
throughline: open, self-hostable standards, and as little reliance on
|
throughline: open, self-hostable standards, and as little reliance on
|
||||||
third-party services as I can manage.
|
third-party services as I can manage.
|
||||||
@@ -29,14 +29,14 @@ import { LEGAL } from '../consts';
|
|||||||
the repo.
|
the repo.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Typefaces are <a href="https://rsms.me/inter/" rel="noopener">Inter</a>
|
Typefaces are <a href="https://rsms.me/inter/" rel="noopener">Inter</a>{' '}
|
||||||
and <a href="https://www.jetbrains.com/lp/mono/" rel="noopener">JetBrains
|
and <a href="https://www.jetbrains.com/lp/mono/" rel="noopener">JetBrains
|
||||||
Mono</a>, self-hosted via Fontsource — no Google Fonts CDN, so no
|
Mono</a>, self-hosted via Fontsource — no Google Fonts CDN, so no
|
||||||
third-party request on page load.
|
third-party request on page load.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Analytics is self-hosted <a href="https://umami.is" rel="noopener">Umami</a>:
|
Analytics is self-hosted <a href="https://umami.is" rel="noopener">Umami</a>:
|
||||||
cookieless, no cross-site tracking, no personal profiles. See the
|
cookieless, no cross-site tracking, no personal profiles. See the{' '}
|
||||||
<a href="/datenschutz">Datenschutzerklärung</a> for what that means.
|
<a href="/datenschutz">Datenschutzerklärung</a> for what that means.
|
||||||
</li>
|
</li>
|
||||||
<li>Icons from <a href="https://iconify.design" rel="noopener">Iconify</a> (Material Design Icons + Simple Icons).</li>
|
<li>Icons from <a href="https://iconify.design" rel="noopener">Iconify</a> (Material Design Icons + Simple Icons).</li>
|
||||||
@@ -47,7 +47,7 @@ import { LEGAL } from '../consts';
|
|||||||
<li><strong>Kotlin</strong> and <strong>Jetpack Compose</strong>, designed in <strong>Material 3 Expressive</strong>.</li>
|
<li><strong>Kotlin</strong> and <strong>Jetpack Compose</strong>, designed in <strong>Material 3 Expressive</strong>.</li>
|
||||||
<li>
|
<li>
|
||||||
No reinvented sync stack — each app is a front-end over a platform
|
No reinvented sync stack — each app is a front-end over a platform
|
||||||
provider (<code>CalendarContract</code>, the OpenTasks
|
provider (<code>CalendarContract</code>, the OpenTasks{' '}
|
||||||
<code>TaskContract</code>) and open standards like CalDAV, iCalendar, and
|
<code>TaskContract</code>) and open standards like CalDAV, iCalendar, and
|
||||||
DecSync.
|
DecSync.
|
||||||
</li>
|
</li>
|
||||||
@@ -69,7 +69,7 @@ import { LEGAL } from '../consts';
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p class="muted">
|
<p class="muted">
|
||||||
This list grows as the stack does. Spotted something you'd ask about?
|
This list grows as the stack does. Spotted something you'd ask about?{' '}
|
||||||
<a href={`mailto:${LEGAL.email}`}>Get in touch</a>.
|
<a href={`mailto:${LEGAL.email}`}>Get in touch</a>.
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
Reference in New Issue
Block a user