10 KiB
Permissions Audit Report & Play Store Declarations
Last Updated: 2026-06-01 Target API Level: 36 (Android 16) Min SDK: 26 (Android 8.0 Oreo)
1. Declared Permissions
1.1 Dangerous / Runtime Permissions
These permissions are requested at runtime with in-app rationale dialogs.
| Permission | Declaration | Requested | Play Store Classification |
|---|---|---|---|
POST_NOTIFICATIONS |
AndroidManifest.xml |
Runtime (API 33+) | Notifications |
RECORD_AUDIO |
AndroidManifest.xml |
Runtime | Microphone |
POST_NOTIFICATIONS — POST_NOTIFICATIONS
- Where used:
MainActivity.kt,FCMService.kt,NotificationChannelManager.kt - Purpose: Deliver real-time security alerts, data exposure warnings, scan completion notices, and marketing communications via system notifications.
- Why it's needed: Kordant is a security monitoring app. Push notifications are the primary mechanism to alert users about threats (data breaches, dark web exposure, spam calls) in a timely manner. Without this permission, users would need to manually open the app to check for threats.
- Rationale shown: "Kordant needs notification access to alert you about security threats and data exposures in real time."
- What happens if denied: Notifications are suppressed. The app continues to function with in-app alert badges. User is guided to Settings to re-enable.
RECORD_AUDIO — Microphone
- Where used:
RecordingScreen.kt(VoicePrint enrollment) - Purpose: Capture voice samples (16kHz mono 16-bit PCM) to create a unique VoicePrint signature for caller verification.
- Why it's needed: VoicePrint technology allows Kordant to detect voice impersonation during phone calls. Enrollment requires recording short voice samples (5–30 seconds) to build a biometric profile. The audio is encrypted in transit and only used for creating the voice signature.
- Why alternatives won't work: This is a biometric feature that inherently requires audio input. No alternative data source can create a voice signature.
- Rationale shown: "Kordant needs microphone access to record voice samples for VoicePrint enrollment and spam call analysis."
- What happens if denied: VoicePrint enrollment is unavailable. Other app features continue to work. User can re-enable from Settings later.
1.2 Normal Permissions (Auto-Granted)
These permissions carry low risk and are automatically granted by the system. No runtime request or Play Store declaration is required.
| Permission | Purpose | Justification |
|---|---|---|
INTERNET |
API communication with Kordant backend | Required for all network operations (TRPC API calls, sync, uploads). |
ACCESS_NETWORK_STATE |
Network connectivity monitoring | Detect network availability before API calls; graceful offline handling. |
RECEIVE_BOOT_COMPLETED |
Re-schedule WorkManager sync after device reboot | Ensures background data sync continues after reboot without user intervention. |
FOREGROUND_SERVICE |
Background sync and call screening | Required by WorkManager for periodic background work (data sync every 15 min) and by CallScreeningService for foreground operation. |
WAKE_LOCK |
Prevent device sleep during sync operations | WorkManager uses wake locks for reliable sync execution. |
UPDATE_WIDGETS |
Update home screen threat score widget | Allows the ThreatScoreWidgetProvider to update the widget with latest threat data. |
BIND_CALL_SCREENING_SERVICE |
Call screening system service binding | Signature-level permission required by android.telecom.CallScreeningService API. Auto-granted. |
USE_BIOMETRIC |
Fingerprint / face unlock authentication | Used by BiometricAuthScreen.kt via androidx.biometric library. Auto-granted. |
1.3 Removed Permissions
These permissions were previously declared but have been removed after audit.
| Permission | Reason for Removal |
|---|---|
READ_PHONE_STATE |
Not required. CallScreeningService obtains caller ID via Call.Details.getHandle() directly without this permission. |
ANSWER_PHONE_CALLS |
Not required. Call blocking is handled by CallScreeningService's CallResponse.Builder.setDisallowCall()/setRejectCall(), which doesn't need this permission. |
USE_FINGERPRINT |
Deprecated permission inherited from androidx.biometric library. Replaced by modern USE_BIOMETRIC. Suppressed via tools:node="remove" in manifest. |
1.4 Permissions Explicitly NOT Declared
The following commonly-requested permissions were considered and rejected:
| Permission | Why Not Needed |
|---|---|
CAMERA |
No document scanning or QR code features. All identity verification is server-side. |
READ_CONTACTS |
Kordant manages its own contact list for watchlist and family features — no device contacts access needed. |
READ_CALL_LOG |
Call screening uses CallScreeningService which provides real-time caller ID without reading call history. |
ACCESS_FINE_LOCATION / ACCESS_COARSE_LOCATION |
No location-based features. |
READ_SMS / RECEIVE_SMS |
No SMS-based authentication or features. |
BLUETOOTH |
No Bluetooth features. |
READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE |
Scoped storage used; no file access needed. |
2. In-App Rationale Dialogs
All sensitive (runtime) permissions are preceded by an in-app rationale dialog:
Flow:
- User triggers a feature requiring a permission
- In-app dialog appears explaining why the permission is needed and the benefit
- User taps "Allow" → System permission dialog appears
- User taps "Maybe Later" → Feature degrades gracefully, no system dialog
- If previously "Never Ask Again" → Settings guidance dialog appears
Rationale Dialogs Implemented:
| Permission | Title | Message | Shown In |
|---|---|---|---|
POST_NOTIFICATIONS |
"Stay Protected" | "...notification access to alert you about security threats..." | MainActivity.kt — NotificationPermissionHandler |
RECORD_AUDIO |
"VoicePrint Access" | "...microphone access to record voice samples for VoicePrint enrollment..." | RecordingScreen.kt — rememberPermissionRequester |
Settings Guidance:
When a permission is permanently denied (user selected "Never Ask Again"), a dialog explains:
- Why the feature won't work without the permission
- How to re-enable it in Settings
- "Open Settings" button linking to app's Settings page
- "Not Now" button to dismiss
3. Graceful Degradation
| Permission Denied | Impact | Handling |
|---|---|---|
POST_NOTIFICATIONS |
No push notifications | App shows in-app alert badges; notification settings section explains how to re-enable; no crashes |
RECORD_AUDIO |
VoicePrint enrollment unavailable | RecordingScreen shows error message; feature button disabled; all other features work |
4. Data Safety Form (Play Console)
Based on the above permission audit, the Play Console Data Safety section should declare:
| Data Type | Collected | Purpose | Shared |
|---|---|---|---|
| Personal Info (Name, Email) | Yes — via OAuth/Google Sign-In | Account creation, authentication | No |
| Phone Number | Yes — for call screening | Spam lookup, call blocking | With spam database service (hashed/anonymized) |
| Audio | Yes — during VoicePrint enrollment | Voice biometric signature | No — encrypted, stored securely |
| App Activity (App interactions, crash logs) | Yes — via Crashlytics | Analytics, crash reporting | No |
| Device or Other IDs | Yes — device ID for FCM | Push notification targeting | No |
5. Testing Matrix
| Test Scenario | Expected Behavior | Status |
|---|---|---|
| First request → rationale → system dialog | In-app rationale appears, then system dialog | ✅ Implemented |
| Allow → feature fully functional | Permission granted, feature works | ✅ Implemented |
| Deny → feature degraded | Feature shows message explaining limited functionality | ✅ Implemented |
| Deny again → Settings guidance | Settings dialog with "Open Settings" button | ✅ Implemented |
| Revoke in Settings → app handles gracefully | App re-evaluates permissions on next use | ✅ Implemented |
| Call screening without role | Shows setup card with "Grant Call Screening Role" button | ✅ Implemented (CallScreeningSettingsScreen) |
| Permission not available (older API) | Feature gracefully hidden or disabled | ✅ Implemented |
6. Code References
| Component | File |
|---|---|
| PermissionManager (centralized) | android/app/src/main/java/com/kordant/android/util/PermissionManager.kt |
| CallScreeningPermissionManager | android/app/src/main/java/com/kordant/android/util/CallScreeningPermissionManager.kt |
| Notification Permission Handler | android/app/src/main/java/com/kordant/android/MainActivity.kt |
| Microphone Permission (RecordingScreen) | android/app/src/main/java/com/kordant/android/ui/screens/voiceprint/RecordingScreen.kt |
| Call Screening Settings / Role Request | android/app/src/main/java/com/kordant/android/ui/screens/services/CallScreeningSettingsScreen.kt |
| Biometric Auth | android/app/src/main/java/com/kordant/android/ui/screens/auth/BiometricAuthScreen.kt |
| Manifest | android/app/src/main/AndroidManifest.xml |
| String Resources | android/app/src/main/res/values/strings.xml |
7. Play Store Justification Summary
When submitting to Play Store, provide the following for sensitive permission declarations:
POST_NOTIFICATIONS
Core Functionality: Kordant is a personal security monitoring application that must deliver real-time alerts about data breaches, dark web exposure, identity theft risks, and spam call detection. Push notifications are the primary alert mechanism for time-sensitive security threats. The app also delivers scan completion notices and system status updates. Without notification access, users would need to manually check the app for critical security information, defeating the purpose of a proactive security tool.
RECORD_AUDIO
Core Functionality: Kordant's VoicePrint feature creates a biometric voice signature to detect voice impersonation and unauthorized callers. This requires capturing a short voice sample (5-30 seconds) during enrollment. The audio is encrypted at every stage: during capture, during transmission, and at rest. No audio recordings are ever shared with third parties or used for any purpose other than voice signature creation. The feature is fully opt-in and can be used without any other app features being affected.