
Notification Guard filters incoming Android notifications against weekday + time-based profiles (night, lunch break, working hours, weekend, custom) and fully custom per-app rules with multiple exception types per rule (keyword or contact). A hardcoded privacy filter ensures that notifications from sensitive app categories — banking, authenticator, medical, public-sector — are always let through without their content ever entering the store.
| Property | Value |
|---|---|
| Platform | Android 7+ (API 24) |
| Stack | Tauri v2 · Rust · Svelte 5 |
| Languages | 7 |
| Repository | git.pronix.org/oiv1Ni3o/notification-guard |
flowchart LR
A[App notifications] --> B[Local capture<br/>on-device only]
B --> C[(Encrypted local storage)]
C --> D[User view]
D --> E[Manual export]
B -.->|never| F[("Cloud / Server")]
style F stroke-dasharray: 5 5,stroke:#c00,color:#c00
Local-only architecture. No server, no account, no tracking, no analytics. The Android manifest declares no internet permission.
android.permission.INTERNET)The NotificationListenerService unavoidably sees every notification.
A pre-filter sorts sensitive app categories out BEFORE the rules engine
ever sees them — these notifications never enter the store, and their
content is never persisted.
Protected categories (auto-detected):
Regular apps pass through to the rules engine unchanged.
Six hard architectural constraints derived from current Google Play policies (Data Safety, Permissions Declaration, Notification Listener). Each one is tracked as a Gitea issue.
| ID | Requirement | Status & implementation |
|---|---|---|
| C1 | Prominent disclosure & consent | ✓ Met — 4-step wizard covering disclosure, profile selection, category selection, permission activation. Clear notes: local, no server, no network. |
| C2 | No SYSTEM_ALERT_WINDOW | ✓ Met — The manifest does not declare the permission. Re-notifications go through NotificationManager. |
| C3 | Data retention TTL | ✓ Met — Configurable retention (24 h default). Periodic cleanup task (Tokio interval, 60 min). “Clear all” button with confirmation dialog. |
| C4 | Contact picker instead of READ_CONTACTS | ○ Planned — Will be added as an optional opt-in module using the Android Contact Picker — no READ_CONTACTS. |
| C5 | Privacy filter (blocklist of sensitive app categories) | ✓ Met — Hardcoded default blocklist as a pre-filter inside the rules engine. First check in evaluate() — match → immediate Pass, no evaluation, no storage. |
| C6 | No network layer | ✓ Met — Manifest verified (aapt dump badging). No HTTP client dependencies in any Cargo.toml. The app runs entirely in airplane mode. |
Four manifest permissions, each with a concrete functional purpose. No runtime permissions, no restricted special access beyond the core listener.
android.permission.BIND_NOTIFICATION_LISTENER_SERVICE — Core function. Without this permission the app cannot read or filter any notifications. Activated explicitly by the user via system settings.android.permission.RECEIVE_BOOT_COMPLETED — Reconnects the listener service after a device restart. Without it, the app would be blind after every reboot until launched manually.android.permission.WAKE_LOCK — Reliably triggers snooze timers from Doze mode (planned for phase 2).android.permission.POST_NOTIFICATIONS — Surfaces our own re-notifications (released or snoozed) — instead of an overlay window (see C2).svelte-i18n with OS-locale detection via tauri-plugin-os. Available languages: English, German, French, Spanish, Chinese, Japanese, Korean.NotificationListenerService bridges events through the Tauri plugin API into the Rust pipeline.rusqlite (WAL, foreign keys on). 5 migrations. App-private file, no external access.notif-listener, rules-engine, notif-store) have no cross-dependencies. Communication goes exclusively through the Tauri host as a mediator.Notification Guard — Repository: git.pronix.org/oiv1Ni3o/notification-guard