fix: security hardening — Keychain, no hardcoded creds, safe URLs
- Add KeychainService for encrypted token storage (auth, refresh, health JWT, API key) - Remove hardcoded email/password from HealthAPIService, store in Keychain - Move all tokens from UserDefaults to Keychain - API key sent via X-API-Key header instead of URL query parameter - Replace force unwrap URL(string:)! with guard let + throws - Fix force unwrap Calendar.date() in HealthKitService - Mark HealthKitService @MainActor for thread-safe @Published - Use withTaskGroup for parallel habit log fetching in TrackerView - Check notification permission before scheduling reminders - Add input validation (title max 200 chars) - Add privacy policy and terms links in Settings - Update CLAUDE.md with security section Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -157,13 +157,16 @@ class NotificationService {
|
||||
cancelReminder("morning_reminder")
|
||||
cancelReminder("evening_reminder")
|
||||
|
||||
if morning {
|
||||
let parts = morningTime.split(separator: ":").compactMap { Int($0) }
|
||||
if parts.count == 2 { scheduleMorningReminder(hour: parts[0], minute: parts[1]) }
|
||||
}
|
||||
if evening {
|
||||
let parts = eveningTime.split(separator: ":").compactMap { Int($0) }
|
||||
if parts.count == 2 { scheduleEveningReminder(hour: parts[0], minute: parts[1]) }
|
||||
Task {
|
||||
guard await isAuthorized() else { return }
|
||||
if morning {
|
||||
let parts = morningTime.split(separator: ":").compactMap { Int($0) }
|
||||
if parts.count == 2 { scheduleMorningReminder(hour: parts[0], minute: parts[1]) }
|
||||
}
|
||||
if evening {
|
||||
let parts = eveningTime.split(separator: ":").compactMap { Int($0) }
|
||||
if parts.count == 2 { scheduleEveningReminder(hour: parts[0], minute: parts[1]) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user