Skip to content

Keryx alert data classification and local storage

Approved: 25 August 2026

This document is the P1-05 production data-classification, retention, and local-storage policy for Keryx for SafeCall. It inventories QR, alert, native, notification, and support data; classifies sensitivity and roles; and records approved launch controls for SharedPreferences storage and full lock-screen previews.

It does not claim that encrypted platform storage, redacted lock-screen builders, privacy policy pages, or store forms exist. Implementation of later hardening and disclosure text remains other work items.

Purpose and non-goals

Purpose

  • Inventory data that crosses QR, device storage, OS notifications, native prefs, and support channels.
  • Classify sensitivity and controller/processor roles for honest privacy and store disclosures.
  • Approve retention, deletion, tombstones, backups, lock-screen exposure, device-loss, and diagnostic redaction for launch.
  • Feed #99#101 and related support work.

Non-goals

  • Changing Dart stores, OS notification builders, or backup entitlements.
  • Moving secrets to Keychain / EncryptedSharedPreferences for this work item.
  • Publishing privacy/terms pages or filling Apple/Play forms.
  • Implementing ntfy token revoke UX (owned by P1-02 implementation and #120/ #121).
  • Adding an analytics or crash SDK (prohibited at launch by P0-05).

Approved decisions

  • Owner and approver: Thomas Minitsios, 25 August 2026.
  • Lock-screen preview: full OS notification title + body for launch; policies and store forms must disclose lock-screen exposure.
  • Storage protection: SharedPreferences is acceptable for local config (including future subscribe_auth), pause flag, and alert history for launch. Platform secure storage is not a launch blocker. Treat subscribe_auth as a secret in documentation and support even while prefs-backed.
  • Visible retention: latest 200 active + archived messages.
  • Tombstones: up to 500 deleted tombstones to suppress ntfy-cache reintroduction; not a user-visible archive.

Roles

RolePartyScope
App publisher / product controller for the app binary and store listingssourcectlApp design, store privacy answers, in-app processing on device as shipped
Hosted alert transport processorClient deployer of the ntfy host (and any APNs/FCM upstream they configure)Message cache, ACL, upstream wakes; see #119
SafeCall platform operatorContracted SafeCall deployment operatorAlert generation and publish path; publish token custody
Device / local copy controllerSafeCall administrator who installs and provisions Keryx on their deviceLocal config, history, OS notifications, device backups, reset

Ordinary administrators do not configure ntfy topics; they select friendly categories and scan a QR on their own device.

Data inventory and classification

Sensitivity scale: Secret (credential), High (operational alert or subscribe capability), Medium (transport/debug metadata), Low (non-identifying flags).

DataSensitivityPurposeStorage today / targetRetentionBackup exposureNotes
QR payload / local config (ntfy_server_url, topics, labels, created_at, debug_access)HighProvision subscribe path and UI labelsSharedPreferences keryx_configUntil reset/uninstall or replace QRMay enter OS device backupv1 today; v2 adds secret below
subscribe_auth / token_id (v2)Secret / MediumAuthenticated subscribe; support correlationSharedPreferences with config (launch-approved)Until reset/uninstall or revoke+replaceMay enter OS device backupNever show in ordinary or debug UI; revoke is offboarding
Topic namesHighRouting; may enable guessing on open hostsConfig, history, debug UI if enabledWith config/historyBackup with prefsPrefer friendly labels in ordinary UI
Friendly labelsMediumAdministrator-facing category namesConfigWith configBackup with prefs
Alert title / bodyHighDeliver SafeCall alert; may include device name, MAC, operational or location-like contentSharedPreferences history; OS notification UILatest 200 visible; then dropBackup with prefs; lock-screen visibleFull lock-screen preview approved
Raw ntfy JSONHighDedupe, debug, tag/priority recoverySharedPreferences with message recordWith visible message or until tombstone overflowBackup with prefsDebug UI only when debug_access
Tags / priority / timestamps / message idMedium–HighDisplay, sort, poll sinceHistory + native last-message idsWith history / subscription prefsBackup with prefs
Tombstones / dedupe keysMediumPrevent deleted alerts from returning via cache pollSharedPreferences (deleted status)Cap 500Backup with prefsNot user-visible archive
Pause flagLowSuppress notifications while configuredSharedPreferences keryx_pausedUntil changed/resetBackup with prefs
Parsed alert condition state / known devicesHighAuthoritative category cards and per-device controlsSharedPreferences alert-state storeUntil reset/new QR; bounded to known alert subjectsBackup with prefsContains the same device identifiers and summaries already present in alert bodies
Category and per-device notification policyMediumLocal rolling-window suppressionSharedPreferences policy store plus native policy snapshotUntil changed/reset/new QRBackup with prefsSuppression never removes the underlying alert from history/state
Native last-notified timestamps and message dedupe idsMediumApply policy consistently during background deliveryVendored plugin preferencesBounded/pruned; until reset/unsubscribePlatform-dependentNative mutable delivery state is separate from the Dart-owned policy
Native Android subscription prefs (URL, topics, auth, last ids)Secret–HighPlugin subscribe/restartVendored plugin SharedPreferences / device-protected contextUntil clear/unsubscribeMay backup with app dataAlign with P1-02/P1-03 implementation
APNs / FCM device tokens (when implemented)SecretWake registration on client ntfyPer iOS / Android designsUntil delete/resetPlatform-dependentNot sent to SafeCall HTTP APIs
OS lock-screen notification contentHighImmediate administrator awarenessOS notification shade / lock screenUntil dismissed or OS clearsN/A (ephemeral UI)Full title+body approved; disclose
Debug diagnosticsMedium–HighRestricted troubleshootingIn-app detail when debug_accessSession / stored message lifetimeScreenshots riskNo secrets; minimize in tickets
Support tickets / intakeHigh if payloads attachedField diagnosisExternal support channelPer SafeCall support processN/ARedact secrets; minimize raw JSON (#132)
Analytics / crash SDK identifiersNot collected at launchP0-05

Approved launch controls

Storage protection

  • SharedPreferences for Flutter config and notification history is approved for launch, including future storage of subscribe_auth in that config blob.
  • Documentation and support must still call subscribe_auth a secret.
  • Optional later migration to Keychain / EncryptedSharedPreferences is a deferred improvement, not a launch requirement under this approval.

Lock-screen and OS notifications

  • Full title and body (including emoji tags where shown) may appear on the lock screen and notification shade.
  • #99#101 must disclose that alert content can appear on a locked device.
  • Redacted lock-screen previews are not required for launch.

Retention, delete, and reset

ControlLaunch rule
Visible messagesCap at latest 200 active + archived combined (current NotificationStore.maxMessages)
TombstonesCap at 500 deleted records; purpose is cache-poll suppression only
Per-item delete / delete-all archivedLocal only; creates tombstones as implemented today
Reset AppClears local config, history, parsed condition state, policy, and native delivery state; does not revoke ntfy subscribe token
OffboardingRequire revoke by token_id on the ntfy host, then local reset/uninstall (P1-02, #120/#121)

Device backups

  • Accept default OS backup behavior of app preferences for launch.
  • Disclose that backups may contain alert history, topic metadata, and config secrets (including subscribe_auth after v2).
  • Excluding prefs from backup or encrypting backup contents is a later improvement, not a launch blocker.

Device loss and replacement

  • A holder of a lost/stolen provisioned device can read local history and may continue receiving alerts until the subscribe token is revoked and the device is wiped or reset.
  • Replacement: mint a new QR/token, revoke the old token, then reset or uninstall the old device when available.
  • Local reset alone is not sufficient offboarding (threat model A7/A10).

Diagnostic redaction

  • Ordinary Active/Archive/detail UI: message and received time; no subscribe_auth, no APNs/FCM tokens, no publish credentials.
  • debug_access QR may show topic names, ntfy ids, tags, priority, and raw JSON; still must not show subscribe_auth.
  • Support intake (#132) and privacy copy (#99): redact secrets; avoid pasting full raw payloads unless necessary and time-bounded.

Mapping to threat model

Abuse caseHow this policy treats it
A7 device lossDocuments local exposure; offboarding requires P1-02 revoke + wipe
A8 debug overexposureLimits secrets in debug; debug_access remains restricted
A9 log leakageNo analytics SDK; support redaction process
A10 offboardingLocal reset insufficient; revoke required

Residual A7/A10 risk remains until revoke UX and deployer ACL are live.

Explicit non-claims

Closing #98 approves this policy. It does not:

  • move secrets to platform secure storage;
  • change lock-screen notification builders;
  • implement token revoke or offboarding UI;
  • publish privacy/terms URLs or complete Apple/Play forms;
  • claim alert bodies never contain personal or location-like data.

Implementation and disclosure handoffs

WorkOwner
Privacy, terms, and support commitments matching this inventory#99 — DRAFT package in legal/; live publish remains #107
Apple privacy / encryption / nutrition answers#100
Play Data Safety and related declarations#101
Safety claims if lock-screen exposure matters operationally#103
Device-loss, reset, and offboarding administrator guidance#120, #121
Support intake redaction#132
Optional secure-storage hardeningDeferred; not launch-required
v2 subscribe_auth stored in prefsLater P1-02 implementation; follows this storage approval

Review record

  • Status: approved as the P1-05 data classification and local-storage policy.
  • Date: 25 August 2026.
  • Approver: Thomas Minitsios under the P0-05 RACI.
  • Depends on: P1-01 threat model, P1-02 provisioning protocol.
  • Evidence sources: keryx/lib/services/notification_store.dart, keryx/lib/services/keryx_config_store.dart, keryx/lib/models/ntfy_message.dart, keryx/lib/screens/notification_detail_screen.dart, keryx/lib/screens/home_screen.dart, vendored Android notification/prefs paths, docs/gtm/keryx/threat-model.md.