ZIP code was US-only and redundant now that the suggestion engine
uses home profile features (heating, pool, etc.) for personalization.
Onboarding flow: Welcome → Value Props → Name → Account → Verify →
Home Profile → Task Selection (was: ...Verify → ZIP → Home Profile...)
Removed regionalTemplates references from task selection view.
Both iOS and Compose flows updated.
New onboarding step: "Tell us about your home" with chip-based pickers
for systems (heating/cooling/water heater), features (pool, fireplace,
garage, etc.), exterior (roof, siding), interior (flooring, landscaping).
All optional, skippable.
Tabbed task selection: "For You" tab shows personalized suggestions
based on home profile, "Browse All" has existing category browser.
Removed 5-task limit — users can add unlimited tasks.
Removed subscription upsell from onboarding flow — app is free.
Fixed picker capsule squishing bug with .fixedSize() modifier.
Both iOS and Compose implementations updated.
Android: uncaught exception handler sends $exception events with stack
trace to PostHog, flushes before delegating to default handler.
iOS: NSSetUncaughtExceptionHandler captures crashes via PostHogSDK,
avoids @MainActor deadlock by calling SDK directly.
Common: captureException() available for non-fatal catches app-wide.
Platform stubs for jvm/js/wasmJs.
Biometric lock: opt-in Face ID/Touch ID/fingerprint app lock with toggle
in ProfileScreen. Locks on background, requires auth on foreground return.
Platform implementations: BiometricPrompt (Android), LAContext (iOS).
Rate limit: 429 responses parsed with Retry-After header, user-friendly
error messages in all 10 locales, retry plugin respects 429.
ErrorMessageParser updated for both iOS Swift and KMM.
- DELETE /api/auth/account/ API call in AuthApi + APILayer
- authProvider field on User model for email vs social auth detection
- DeleteAccountDialog with password (email) or "type DELETE" (social) confirmation
- Red "Delete Account" card on ProfileScreen
- Navigation wired in App.kt (clears data, returns to login)
- 10 i18n strings in strings.xml
- ViewModel unit tests for delete account state
Backend now returns Document directly instead of wrapped
DocumentActionResponse. Remove unused DocumentActionResponse class.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Update DEV API URLs from treytartt.com to api.myhoneydue.com
- Add rounded corners to app icon in login, register, and onboarding screens
- Add 9 missing English translations in Localizable.xcstrings
- Fix property feature pills to use equal height for balanced layout
- Remove duplicate honeyDue user scheme
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fetch regional templates by ZIP during onboarding and display categorized
task suggestions (iOS + KMM shared layer)
- Fix multi-expand for task categories (toggle independently, not exclusive)
- Fix ScrollViewReader auto-scroll to expanded category sections
- Fix UUID stability bug: cache task categories to prevent ID regeneration
that caused silent task creation failures
- Fix stale data after onboarding: force refresh residences and tasks in
RootView onComplete callback
- Fix address formatting: show just ZIP code when city/state are empty
instead of showing ", 75028" with leading comma
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Completion animations: play user-selected animation on task card after completing,
with DataManager guard to prevent race condition during animation playback.
Works in both AllTasksView and ResidenceDetailView. Animation preference
persisted via @AppStorage and configurable from Settings.
- Subscription: add trial fields (trialStart, trialEnd, trialActive) and
subscriptionSource to model, cross-platform purchase guard, trial banner
in upgrade prompt, and platform-aware subscription management in profile.
- Analytics: disable PostHog SDK debug logging and remove console print
statements to reduce debug console noise.
- Documents: remove redundant nested do-catch blocks in ViewModel wrapper.
- Widgets: add debounced timeline reloads and thread-safe file I/O queue.
- Onboarding: fix animation leak on disappear, remove unused state vars.
- Remove unused files (ContentView, StateFlowExtensions, CustomView).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The createCompletionWithImages method used client.post() with a manual
MultiPartFormDataContent body, which can override the Authorization header.
Switch to submitFormWithBinaryData() (matching DocumentApi's working pattern)
which properly separates form data from request headers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change ApiConfig.CURRENT_ENV from LOCAL to DEV
- Add "Google Sign-In Error" and "Sign in with Google" to Localizable.xcstrings
- Reorder Xcode project build settings (cosmetic)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remediate all P0-S priority findings from cross-platform architecture audit:
- Harden token storage with EncryptedSharedPreferences (Android) and Keychain (iOS)
- Add SSL pinning and certificate validation to API clients
- Fix subscription cache race conditions and add thread-safe access
- Add input validation for document uploads and file type restrictions
- Refactor DocumentApi to use proper multipart upload flow
- Add rate limiting awareness and retry logic to API layer
- Harden subscription tier enforcement in SubscriptionHelper
- Add biometric prompt for sensitive actions (Login, Onboarding)
- Fix notification permission handling and device registration
- Add UI test infrastructure (page objects, fixtures, smoke tests)
- Add CI workflow for mobile builds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix residence detail not updating after edit:
- DataManager.updateResidence() now updates both _residences and _myResidences
- ResidenceViewModel auto-updates selectedResidence when data changes
- No pull-to-refresh needed after editing
- Add widget theme support:
- Widgets now use user's selected theme via App Group UserDefaults
- ThemeManager has simplified version for widget extension context
- Added WIDGET_EXTENSION compiler flag to CaseraExtension target
- Redesign widget views with organic aesthetic:
- Updated FreeWidgetView, SmallWidgetView, MediumWidgetView, LargeWidgetView
- Created OrganicTaskRowView, OrganicStatsView, OrganicStatPillWidget
- Document patterns in CLAUDE.md:
- Added Mutation & Auto-Update Pattern section
- Added iOS Shared Components documentation
- Documented reusable buttons, forms, empty states, cards, modifiers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- APILayer.getResidence() now checks both residences and myResidences caches
- Home screen loads myResidences, but getResidence() only checked residences,
causing unnecessary network calls on every residence detail visit
- Remove flawed iOS-side cache check in TaskViewModel that had race condition
with Kotlin StateFlow - let Kotlin handle all caching logic
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix TokenStorage.getToken() returning stale cached token after login/logout
- Add comprehensive ErrorMessageParser with 80+ error code mappings
- Add Suite9 and Suite10 UI test files for E2E integration testing
- Fix accessibility identifiers in RegisterView and ResidenceFormView
- Fix UITestHelpers logout to target alert button specifically
- Update various UI components with proper accessibility identifiers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove summary field from MyResidencesResponse and TaskColumnsResponse
- Update HomeScreen and ResidencesScreen to observe DataManager.totalSummary
- Load tasks when residence views appear to ensure accurate summary
- Add pull-to-refresh for tasks on ResidencesScreen
- Update iOS views to use client-side calculated summary
Summary is now calculated via refreshSummaryFromKanban() from cached
kanban data. This ensures summary is always up-to-date after CRUD
operations and when residence views are shown.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The setAllTasks() function was not calling refreshSummaryFromKanban()
after loading kanban data, so the summary statistics (totalTasks,
totalOverdue, etc.) were never calculated - they stayed at zero.
Also switch API environment back to DEV.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update ErrorResponse model to make detail and statusCode optional since
backend now returns simple {"error": "message"} format
- Update AuthApi to parse actual backend error messages instead of generic
"Registration failed"/"Login failed" strings
- Update ErrorParser to prioritize the "error" field and add fallback for
simple error map responses
- Update iOS ViewModels (Login, Register, AppleSignIn) to properly handle
400 and 409 status codes by displaying backend error messages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CompleteTaskScreen for full-screen task completion (matches iOS CompleteTaskView)
- Add ManageUsersScreen for full-screen user management (matches iOS ManageUsersView)
- Add PhotoViewerScreen with swipeable gallery and pinch-to-zoom
- Add UpgradeScreen for full-screen subscription flow (matches iOS UpgradeFeatureView)
- Add navigation routes for new screens (CompleteTaskRoute, ManageUsersRoute, PhotoViewerRoute, UpgradeRoute)
- Wire navigation callbacks into AllTasksScreen, ResidenceDetailScreen, ProfileScreen
- Add overdue count with red color to Summary Card
- Add pulsing animation to residence cards when overdue
- Add property type, isPrimary star, and street address to Residence Card
- Add Edit Profile, Privacy Policy, and App Version to ProfileScreen
- Add string resources for new UI elements and localization
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move Easy Share (.casera file) section above Share Code section in the
invite users dialog. Both platforms now have consistent UI with both
buttons using the same filled button style.
iOS changes:
- Move share functionality into ManageUsersView
- Remove share button from ResidenceDetailView toolbar
- Redesign ShareCodeCard with Easy Share on top
Android changes:
- Update ManageUsersDialog with matching layout
- Connect share package callback to existing share function
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add calculateSummaryFromKanban() to compute summary stats from cached kanban data
- Add refreshSummaryFromKanban() called after task CRUD operations
- Fix column name matching to use API format (e.g., "overdue_tasks" not "overdue")
- Fix tasksDueNextMonth to only include due_soon tasks (not upcoming)
- Update TaskResponse computed properties to resolve from DataManager cache
- Update iOS task cards to use computed properties for priority/frequency/category
- This enables API to skip preloading lookups for better performance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Load contractors during initializeLookups() when authenticated
- Update getContractorsByResidence() to filter from cache instead of making network call
- Only fetch from API if cache is empty or stale
This eliminates the /contractors/by-residence/{id}/ call when visiting residences.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add customIntervalDays field to Kotlin models (TaskResponse, TaskCreateRequest, TaskUpdateRequest)
- Update Android AddTaskDialog to show interval field only for "Custom" frequency
- Update Android EditTaskScreen for custom frequency support
- Update iOS TaskFormView for custom frequency support
- Fix preview data in TaskCard and TasksSection to include new field
- Add customIntervalDays to OnboardingFirstTaskView
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add platform haptic feedback abstraction (HapticFeedback.kt) with
implementations for Android, iOS, JVM, JS, and WASM
- Enhance CompleteTaskDialog with interactive 5-star rating, image
thumbnails, and haptic feedback
- Add ImageBitmap platform abstraction for displaying selected images
- Localize TaskTemplatesBrowserSheet with string resources
- Add Android widgets infrastructure (small, medium, large sizes)
- Add Google Sign-In button components and auth flow preparation
- Update strings.xml with new localization keys for completions,
templates, and document features
- Integrate haptic feedback into ThemePickerDialog
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Send the device's IANA timezone identifier (e.g., "America/Los_Angeles")
with every API request to enable timezone-aware overdue task detection.
Platform implementations:
- Android/JVM: TimeZone.getDefault().id
- iOS: NSTimeZone.localTimeZone.name
- JS/WASM: Intl.DateTimeFormat().resolvedOptions().timeZone
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ErrorMessageParser in Kotlin and Swift to detect network errors
and technical messages, replacing them with human-readable text
- Update all ViewModels to use ErrorMessageParser.parse() for error display
- Remove redundant error popup from LoginView (error shows inline only)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add nextDueDate field to TaskResponse model (from API's next_due_date)
- Add effectiveDueDate computed property (nextDueDate ?? dueDate)
- Update DynamicTaskCard, TaskCard to display effectiveDueDate
- Update WidgetDataManager to save effectiveDueDate to widget cache
- Update TaskFormView to use effectiveDueDate when editing
- Fix preview mock data to include nextDueDate parameter
This ensures recurring tasks show the correct next due date after completion
instead of the original due date.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add deep link navigation from push notifications to specific task column on kanban board
- Fix subscription check in push notification handler to allow navigation when limitations disabled
- Add pendingNavigationTaskId to handle notifications when app isn't ready
- Add ScrollViewReader to AllTasksView for programmatic scrolling to task column
- Add canShareResidence() and canShareContractor() subscription checks (iOS & Android)
- Add test APNS file for simulator push notification testing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
DataManager.removeResidence() now also updates _myResidences so the
residence list view updates immediately without requiring a manual refresh.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove TaskStatus model and status_id foreign key references
- Add in_progress boolean field to task models and forms
- Update TaskApi to use dedicated POST endpoints for task actions:
- POST /tasks/:id/cancel/ instead of PATCH with is_cancelled
- POST /tasks/:id/uncancel/
- POST /tasks/:id/archive/
- POST /tasks/:id/unarchive/
- Fix iOS TaskViewModel to use error-first pattern for Kotlin-Swift
generic type bridging issues
- Update iOS callback signatures to pass full TaskResponse instead
of just taskId to avoid stale closure lookups
- Add in_progress localization strings
- Update widget preview data to use inProgress boolean
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Frontend changes:
- Add generic WithSummaryResponse<T> model for CRUD responses
- Update TaskApi, TaskCompletionApi, ResidenceApi return types
- Update APILayer to extract summary from responses and call DataManager.setTotalSummary()
- Replace refreshTasks() calls with DataManager.updateTask() for local cache updates
- Remove redundant refreshMyResidences() calls
- Remove unused helper methods (refreshTasks, refreshMyResidences, refreshSummary)
- Add summary field to JoinResidenceResponse model
This pairs with the backend changes to eliminate redundant network calls
after CRUD operations - dashboard stats now update from the mutation response.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add dailyDigest and dailyDigestHour fields to Kotlin NotificationPreference model
- Update NotificationPreferencesViewModel to support new fields
- Add Daily Summary toggle with time picker to Android NotificationPreferencesScreen
- Add Daily Summary toggle with time picker to iOS NotificationPreferencesView
- Add localized strings for Daily Summary in all 10 languages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add overdueCount field to ResidenceResponse model
- ResidenceCard shows PulsingIconView when residence has overdue tasks
- SummaryCard uses static CaseraIconView (never pulses)
- APILayer refreshes residence data after task completion to update
overdue counts and animation state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Allow users to customize when they receive notification reminders:
- Add hour fields to NotificationPreference model
- Add timezone conversion utilities (localHourToUtc, utcHourToLocal)
- Add time picker UI for iOS (wheel picker in sheet)
- Add time picker UI for Android (hour chip selector dialog)
- Times stored in UTC, displayed in user's local timezone
- Add localized strings for time picker UI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add SharedResidence model and package type detection for .casera files
- Add generateSharePackage API endpoint integration
- Create ResidenceSharingManager for iOS and Android
- Add share button to residence detail screens (owner only)
- Add residence import handling with confirmation dialogs
- Update Quick Look extensions to show house icon for residence packages
- Route .casera imports by type (contractor vs residence)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- DataManager now persists lookup data (residence types, task categories,
priorities, statuses, specialties, templates) to disk
- Loads cached lookups on app startup for faster launch
- iOS: Refresh lookups when app becomes active, refresh widget on background
- Android: Initialize DataManager in onCreate, already had onResume refresh
- Only send ETag if lookup data is actually in memory to avoid 304 with no data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>