# SPDX-License-Identifier: AGPL-3.0-or-later # # Flatpak manifest for Plainnote. # # Built from the .deb artifact that `tauri build --bundles deb` produces, so # we don't re-compile Rust inside flatpak-builder's sandbox. The release # workflow (.github/workflows/release.yml) runs: # # 1. tauri build --bundles appimage,deb (produces apps/desktop/src-tauri/target/release/bundle/deb/*.deb) # 2. flatpak-builder --repo=repo --force-clean build packaging/flatpak/dev.plainnote.app.yml # 3. flatpak build-bundle repo plainnote.flatpak dev.plainnote.app # # App ID: matches `identifier` in tauri.conf.json. Do not change without # updating tauri.conf.json, the .desktop file inside the .deb, and any # D-Bus references. # # Runtime: org.gnome.Platform//49 (NOT org.freedesktop.Platform). # Tauri 2 dynamically links against libwebkit2gtk-4.1.so.0 — that # library is shipped by org.gnome.Platform but NOT by org.freedesktop # .Platform. A Tauri app built against the freedesktop runtime # installs but errors at startup with: # error while loading shared libraries: libwebkit2gtk-4.1.so.0: # cannot open shared object file: No such file or directory # # GNOME runtimes EOL on a ~12-month cycle. As of mid-2026 the supported # branches are 49 (active to ~Sept 2026) and 50. We target 49: still # ships webkit2gtk-4.1 (the ABI Tauri 2 ≤ 2.11 needs) and has had # more bake time than 50. Re-evaluate every 6 months — bumping the # runtime version is itself a security event since users see a fresh # permission prompt at upgrade. app-id: dev.plainnote.app runtime: org.gnome.Platform runtime-version: '49' sdk: org.gnome.Sdk command: plainnote # flatpak-builder's post-build phase runs 'appstream-compose' to compile # AppStream metadata + cache icons. That binary was renamed to # 'appstreamcli compose' in newer appstream releases; the legacy name # isn't shipped in Sdk//24.08, so flatpak-builder errors with # "bwrap: execvp appstream-compose: No such file". Skip the step — # our hand-written metainfo.xml is already installed at # /app/share/metainfo and is what GNOME Software / Flatpak actually # read. We lose nothing by skipping the recompile. appstream-compose: false # ───────────────────────────────────────────────────────────────────── # finish-args — sandbox permissions exposed to the running app. # # Plainnote's spec is privacy-first (no telemetry, no cloud, files-on-disk # authoritative). The principle below: grant the MINIMUM needed for v0.1 # features to work. Every entry is justified with the feature it enables. # ───────────────────────────────────────────────────────────────────── finish-args: # Display: standard for any GTK/WebKit GUI app. Wayland-first, X11 fallback. - --socket=wayland - --socket=fallback-x11 - --share=ipc # required by --socket=fallback-x11 # GPU acceleration: WebKit2GTK uses Mesa via DRI for canvas, transforms, # and the graph view's force-directed layout. Without this, the graph # view falls back to software rendering and pegs a CPU core at 5k nodes. - --device=dri # D-Bus / notifications: notify-rust talks straight to # org.freedesktop.Notifications. Required for reminder delivery. We use # D-Bus directly rather than xdg-desktop-portal::Notification because the # portal API is async and more verbose for the same outcome. - --talk-name=org.freedesktop.Notifications # Filesystem: vault location is user-configurable in Settings. Restricting # to xdg-documents would break users who keep their vault elsewhere # (~/notes, mounted external drives, etc). Users who want a tighter # scope can run `flatpak override --user --nofilesystem=home # --filesystem=~/specific/path dev.plainnote.app`. - --filesystem=home # ──────────────────────────────────────────────────────────────────── # NOT GRANTED — and why. Re-grant later only with a justification. # ──────────────────────────────────────────────────────────────────── # --share=network : v0.1 ships zero network features. P2P sync # will need this in v0.2; until then, the app # is offline-only and that's a hard guarantee. # --talk-name=org.freedesktop.secrets : we don't use libsecret. # --filesystem=host : would expose /, /usr, /opt — the vault never # needs to read system paths. # --device=all : --device=dri is the only hardware we need. # --talk-name=ca.desrt.dconf : we read prefers-color-scheme via CSS, # not via gsettings. # ───────────────────────────────────────────────────────────────────── # Build modules — repackage the .deb that Tauri already produced. # # build-commands run inside flatpak-builder's sandbox. Outside /app # the filesystem is READ-ONLY — extract the .deb to a build-dir scratch # space, then `install` the files we need into /app/. # ───────────────────────────────────────────────────────────────────── modules: - name: plainnote buildsystem: simple build-commands: # 1. Extract the .deb's data.tar.* into a writable scratch dir. # The .deb is an `ar` archive; data.tar.* may be gzipped, xz'd, # or zstd'd depending on dpkg version on the build host. - mkdir -p _extracted - ar x plainnote.deb data.tar.gz || ar x plainnote.deb data.tar.xz || ar x plainnote.deb data.tar.zst - tar -xf data.tar.* -C _extracted # 2. Install binary, .desktop, metainfo, and icons into /app/. # Note the desktop file is 'Plainnote.desktop' (capital P) — # that's how Tauri 2 names it from productName="Plainnote". - install -Dm755 _extracted/usr/bin/plainnote /app/bin/plainnote - install -Dm644 _extracted/usr/share/applications/Plainnote.desktop /app/share/applications/dev.plainnote.app.desktop - install -Dm644 dev.plainnote.app.metainfo.xml /app/share/metainfo/dev.plainnote.app.metainfo.xml # 3. Icons: copy every size shipped, renaming to match the app-id. # The .deb only contains the sizes Tauri generated; missing # sizes are skipped silently rather than failing the build. - | for size in 32x32 128x128 256x256 512x512; do src="_extracted/usr/share/icons/hicolor/${size}/apps/plainnote.png" dst="/app/share/icons/hicolor/${size}/apps/dev.plainnote.app.png" [ -f "$src" ] && install -Dm644 "$src" "$dst" || true done # 4. Patch the .desktop file: Exec must be the bare command name # (Flatpak resolves it via /app/bin), Icon must match the app-id. - | sed -i \ -e 's|^Exec=.*|Exec=plainnote %u|' \ -e 's|^Icon=.*|Icon=dev.plainnote.app|' \ /app/share/applications/dev.plainnote.app.desktop sources: # The CI workflow stages the freshly-built .deb at this path before # invoking flatpak-builder. Local builds: copy the .deb produced by # `npx tauri build --bundles deb` to packaging/flatpak/plainnote.deb. - type: file path: plainnote.deb # The metainfo file lives next to this manifest in-repo; declaring # it as a source copies it into the build dir so install -D can # find it as a relative path. - type: file path: dev.plainnote.app.metainfo.xml