Commit Graph

249 Commits

Author SHA1 Message Date
Trey T
8f86fa2cd0 Fix 12 iOS issues: race conditions, data flow, UX
Critical bugs:
- RootView: auth check deferred to .task{} modifier (after DataManager init)
- DataManagerObservable: map conversion failures now logged with key details
- ContractorViewModel: replace stuck boolean flag with time-based suppression
- DocumentViewModel: guard full success.data before image upload

Logic fixes:
- AllTasksView: 300ms delay before animation flag release
- ResidenceViewModel: trigger initializeLookups() if not ready
- TaskFormView: hasDueDate toggle prevents defaulting to today
- OnboardingState: guard isAuthenticated before completing onboarding

UX fixes:
- ResidencesListView: 10-second refresh timeout
- AllTasksView: add button disabled while sheet presented
- TaskViewModel: actionState auto-resets after 3s, explicit reset on consume
2026-03-26 18:01:49 -05:00
Trey T
4d363ca44e Fix API contract mismatches with Go backend
- Document.purchasePrice: String? → Double? (matches Go decimal.Decimal)
- TaskTemplate: add regionId/regionName (Go returns these, KMM was ignoring)
- TaskResponse.completions: add comment explaining separate fetch pattern
- Document: add comments clarifying fileUrl vs mediaUrl usage
2026-03-26 17:06:36 -05:00
Trey T
e4dc3ac30b Add PostHog exception capture for crash reporting
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.
2026-03-26 16:49:30 -05:00
Trey T
af73f8861b iOS VoiceOver accessibility overhaul — 67 files
New framework:
- AccessibilityLabels.swift: centralized A11y struct with VoiceOver strings
- AccessibilityModifiers.swift: reusable .a11yHeader, .a11yDecorative,
  .a11yButton, .a11yCard, .a11yStatValue View extensions

Shared components: decorative elements hidden, stat views combined,
status/priority badges labeled, error views announced, empty states grouped

Cards: ResidenceCard, TaskCard, DynamicTaskCard, ContractorCard,
DocumentCard, WarrantyCard — all grouped with combined labels,
chevrons hidden, action buttons labeled

Main screens: Login, Register, Residences, Tasks, Contractors, Documents —
toolbar buttons labeled, section headers marked, form field hints added

Onboarding: all 10 views — header traits, button hints, task selection
state, progress indicator, decorative backgrounds hidden

Profile/Subscription: toggle hints, theme selection state, feature
comparison table accessibility, subscription button labels

iOS build verified: BUILD SUCCEEDED
2026-03-26 14:51:29 -05:00
Trey T
0d80df07f6 Add biometric lock and rate limit handling
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.
2026-03-26 14:37:04 -05:00
Trey T
334767cee7 Production hardening: password complexity, token refresh, network resilience
Password complexity: real-time validation UI on register, onboarding, and reset screens
  (uppercase, lowercase, digit, min 8 chars) — Compose + iOS Swift
iOS privacy descriptions: camera, photo library, photo save usage strings
Token refresh: Ktor interceptor catches 401 "token_expired", refreshes, retries
Retry with backoff: 3 retries on 5xx/IO errors, exponential delay (1s base, 10s max)
Gzip: ContentEncoding plugin on all platform HTTP clients
Request timeouts: 30s request, 10s connect, 30s socket
Validation rules: split passwordMissingLetter into uppercase/lowercase (iOS Swift)
Test fixes: corrected import paths in 5 existing test files
New tests: HTTP client retry/refresh (9), validation rules
2026-03-26 14:05:33 -05:00
Trey T
af45588503 Add delete account feature to mobile app
- 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
2026-03-26 10:41:17 -05:00
Trey T
2e5dbaea50 Switch API environment to LOCAL for UI test development
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:06:28 -05:00
Trey T
4df8707b92 UI test infrastructure overhaul — 58% to 96% pass rate (231/241)
Major infrastructure changes:
- BaseUITestCase: per-suite app termination via class setUp() prevents
  stale state when parallel clones share simulators
- relaunchBetweenTests override for suites that modify login/onboarding state
- focusAndType: dedicated SecureTextField path handles iOS strong password
  autofill suggestions (Choose My Own Password / Not Now dialogs)
- LoginScreenObject: tapSignUp/tapForgotPassword use scrollIntoView for
  offscreen buttons instead of simple swipeUp
- Removed all coordinate taps from ForgotPasswordScreen, VerifyResetCodeScreen,
  ResetPasswordScreen (Rule 3 compliance)
- Removed all usleep calls from screen objects (Rule 14 compliance)

App fixes exposed by tests:
- ContractorsListView: added onDismiss to sheet for list refresh after save
- AllTasksView: added Task.RefreshButton accessibility identifier
- AccessibilityIdentifiers: added Task.refreshButton
- DocumentsWarrantiesView: onDismiss handler for document list refresh
- Various form views: textContentType, submitLabel, onSubmit for keyboard flow

Test fixes:
- PasswordResetTests: handle auto-login after reset (app skips success screen)
- AuthenticatedUITestCase: refreshTasks() helper for kanban toolbar button
- All pre-login suites use relaunchBetweenTests for test independence
- Deleted dead code: AuthenticatedTestCase, SeededTestData, SeedTests,
  CleanupTests, old Suite0/2/3, Suite1_RegistrationRebuildTests

10 remaining failures: 5 iOS strong password autofill (simulator env),
3 pull-to-refresh gesture on empty lists, 2 feature coverage edge cases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:05:37 -05:00
Trey t
0ca4a44bac Update DocumentApi for backend activate/deactivate response change
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>
2026-03-18 23:10:05 -05:00
treyt
5c360a2796 Rearchitect UI test suite for complete, non-flaky coverage against live API
- Migrate Suite4-10, SmokeTests, NavigationCriticalPathTests to AuthenticatedTestCase
  with seeded admin account and real backend login
- Add 34 accessibility identifiers across 11 app views (task completion, profile,
  notifications, theme, join residence, manage users, forms)
- Create FeatureCoverageTests (14 tests) covering previously untested features:
  profile edit, theme selection, notification prefs, task completion, manage users,
  join residence, task templates
- Create MultiUserSharingTests (18 API tests) and MultiUserSharingUITests (8 XCUI
  tests) for full cross-user residence sharing lifecycle
- Add cleanup infrastructure: SuiteZZ_CleanupTests auto-wipes test data after runs,
  cleanup_test_data.sh script for manual reset via admin API
- Add share code API methods to TestAccountAPIClient (generateShareCode, joinWithCode,
  getShareCode, listResidenceUsers, removeUser)
- Fix app bugs found by tests:
  - ResidencesListView join callback now uses forceRefresh:true
  - APILayer invalidates task cache when residence count changes
  - AllTasksView auto-reloads tasks when residence list changes
- Fix test quality: keyboard focus waits, Save/Add button label matching,
  Documents tab label (Docs), remove API verification from UI tests
- DataLayerTests and PasswordResetTests now verify through UI, not API calls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:32:13 -05:00
Trey t
cf2e6d8bcc Fix honeycomb grid sizing, alpha, and stroke styling
- Fix hex sizing to use aspectRatio layout instead of GeometryReader
- Remove hardcoded height estimation that caused gap between header and grid
- Set fill alpha to 0.3 and add 0.7 alpha stroke on colored hexagons
- Use 12 rows consistently
- Add forceRefresh parameter to getResidence

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 00:44:41 -05:00
Trey t
7689027bdd Add honeycomb completion heatmap and dev API environment
- Add HoneycombSummaryView component with colored hexagon grid
- Display completion summary on residence detail screen
- Add CompletionSummary model to KMP shared layer
- Add DEV/PROD environment split in ApiConfig
- Fix ResidenceResponse initializers for completionSummary parameter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:05:11 -05:00
Trey t
b8360a2e86 Reformat Localizable.xcstrings whitespace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:23:44 -05:00
Trey t
affc45e1b1 Add honeycomb pattern to widgets and fix PostHog anonymous user tracking
- Widget containerBackground now shows honeycomb texture when toggle is enabled
- Change PostHog personProfiles from .never to .always so anonymous sessions
  and unique visitors are properly counted without identifying users

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:13:19 -06:00
Trey t
73dd440d7b Add honeycomb pattern toggle and make theme switching reactive
Adds a toggleable honeycomb hexagonal grid overlay (matching the website pattern)
that can be enabled independently of any theme via the Appearance screen. Uses a
cached tiled UIImage approach consistent with the existing grain texture system.

Replaces the destructive refreshID-based theme switching (which destroyed all
NavigationStacks and dismissed sheets) with @Observable AppThemeSource. Color
resolution now happens through Swift's Observation framework, so all views using
Color.appPrimary etc. automatically re-render when the theme changes — no view
identity reset needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:36:24 -06:00
Trey t
28339544e5 Update API URL to myhoneydue.com, fix missing translations, and UI polish
- 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>
2026-03-07 11:00:52 -06:00
Trey t
e9f80075c1 Rename Xcode project to honeyDue and fix all bundle IDs
- Rename iosApp.xcodeproj → honeyDue.xcodeproj
- Rename Casera schemes → HoneyDue, HoneyDueExtension, HoneyDueUITests
- Split bundle IDs per-config: Debug=com.tt.honeyDue.dev, Release=com.tt.honeyDue
- Split app groups per-config: Debug=group.com.tt.honeyDue.dev, Release=group.com.tt.honeyDue
- Fix com.t-t. typo → com.tt. in test bundle IDs
- Add APP_GROUP_IDENTIFIER build setting with variable substitution in entitlements
- Replace all hardcoded app group strings in Swift with Info.plist runtime reads
- Remove stale PRODUCT_BUNDLE_IDENTIFIER from Config.xcconfig
- Update test plan container references

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 07:45:12 -06:00
Trey t
8941d4f458 Remove docs, guides, and readmes relocated to old_files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 07:09:37 -06:00
Trey t
d3b6b14e78 Fix build failures from rebrand: restore pbxproj exceptions, fix Kotlin casing, move missed source dirs
- Restore 6 missing PBXFileSystemSynchronizedBuildFileExceptionSet entries
  and exceptions arrays on 5 root groups (lost during sed rename)
- Rename extension WidgetIconView.swift to avoid stringsdata collision
  (original had different names: MyCribIconView vs CaseraIconView)
- Rename CaseraExtension.entitlements → HoneyDueExtension.entitlements
- Fix Kotlin object casing: honeyDueShareCodec → HoneyDueShareCodec,
  honeyDuePackageType → HoneyDuePackageType
- Move missed Kotlin source dirs (jsMain, webMain, androidMain/com/casera)
  to com/tt/honeyDue
- Rename remaining Casera widget files to HoneyDue
- Rename CaseraTests.swift → HoneyDueTests.swift

All 4 projects (Go API, iOS, Android, Web) now compile clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 06:58:56 -06:00
Trey t
1e2adf7660 Rebrand from Casera/MyCrib to honeyDue
Total rebrand across KMM project:
- Kotlin package: com.example.casera -> com.tt.honeyDue (dirs + declarations)
- Gradle: rootProject.name, namespace, applicationId
- Android: manifest, strings.xml (all languages), widget resources
- iOS: pbxproj bundle IDs, Info.plist, entitlements, xcconfig
- iOS directories: Casera/ -> HoneyDue/, CaseraTests/ -> HoneyDueTests/, etc.
- Swift source: all class/struct/enum renames
- Deep links: casera:// -> honeydue://, .casera -> .honeydue
- App icons replaced with honeyDue honeycomb icon
- Domains: casera.treytartt.com -> honeyDue.treytartt.com
- Bundle IDs: com.tt.casera -> com.tt.honeyDue
- Database table names preserved

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 06:33:57 -06:00
Trey t
9c574c4343 Harden iOS app with audit fixes, UI consistency, and sheet race condition fixes
Applies verified fixes from deep audit (concurrency, performance, security,
accessibility), standardizes CRUD form buttons to Add/Save pattern, removes
.drawingGroup() that broke search bar TextFields, and converts vulnerable
.sheet(isPresented:) + if-let patterns to safe presentation to prevent
blank white modals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 09:59:56 -06:00
Trey t
61ab95d108 Polish UI consistency across all CRUD forms and fix data display issues
- Rewrite ResidenceFormView to use standard Form/Section pattern matching TaskFormView
- Remove unused organic form components (OrganicFormSection, OrganicFormTextField, etc.)
- Fix DocumentFormView: NavigationView→NavigationStack, WarmGradientBackground→appBackgroundPrimary, listRowBackground→sectionBackground
- Add Required footer to residence name field and task title/property fields
- Remove redundant Required footers from pickers that always have values
- Fix grey priority dots on kanban cards by guarding PriorityBadge in DynamicTaskCard and TaskCard
- Fix empty frequency labels showing on task cards
- Fix contractor Maps URL building to filter empty strings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:00:40 -06:00
Trey t
48081c0cc8 Add regional task templates to onboarding with multiple bug fixes
- 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>
2026-03-05 15:15:47 -06:00
Trey t
98dbacdea0 Add task completion animations, subscription trials, and quiet debug console
- 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>
2026-03-05 11:35:08 -06:00
Trey t
c5f2bee83f Harden iOS app: fix concurrency, animations, formatters, privacy, and logging
- Eliminate NumberFormatters shared singleton data race; use local formatters
- Add reduceMotion checks to empty-state animations in 3 list views
- Wrap 68+ print() statements in #if DEBUG across push notification code
- Remove redundant .receive(on: DispatchQueue.main) in SubscriptionCache
- Remove redundant initializeLookups() call from iOSApp.init()
- Clean up StoreKitManager Task capture in listenForTransactions()
- Add memory warning observer to AuthenticatedImage cache
- Cache parseContent result in UpgradePromptView init
- Add DiskSpace and FileTimestamp API declarations to Privacy Manifest
- Add FIXME for analytics debug/production API key separation
- Use static formatter in PropertyHeaderCard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:15:42 -06:00
Trey t
bf5d60ca63 Fix iOS analytics by calling Swift AnalyticsManager instead of Kotlin no-op stub
PostHogAnalytics.shared.initialize() was calling the Kotlin actual object which
is a no-op on iOS. Replaced with AnalyticsManager.shared.configure() so the
PostHog SDK actually initializes. Also switched to anonymous-only person profiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:28:27 -06:00
Trey t
233fb08cce Wire KeychainDelegate before DataManager init to fix token persistence
TokenManager.keychainDelegate was never set, so all Keychain reads/writes
failed silently. Tokens couldn't be persisted or loaded on app restart,
and TokenStorage.getToken() returned nil during task completion flows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:14:01 -06:00
Trey t
469d371635 Fix auth header lost on multipart task completion requests
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>
2026-03-02 19:56:13 -06:00
Trey t
cee6be8db2 Switch API environment to DEV and add Google Sign-In localization strings
- 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>
2026-03-02 09:48:03 -06:00
treyt
dc6c60e03d Add subscription feature gating unit tests (SUB-008)
27 new tests covering SubscriptionCacheWrapper: currentTier derivation,
shouldShowUpgradePrompt with per-resource limits and boundary conditions,
canShareResidence/canShareContractor gating, and deprecated prompt property.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:51:11 -06:00
treyt
0c803af9bc Add 4 new unit test suites for greenfield test plan coverage
Add 87 new tests (384 total) covering ValidationRules/ValidationError,
PasswordResetViewModel navigation and client-side validation, WidgetAction
Codable/Equatable/accessors, parseDate, and ThemeID enum properties.
Updates greenfield CSV for AUTH-012/017/018, NOTIF-006/007, WID-003, THEME-002.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:29:12 -06:00
treyt
4679764fdf Fix test build errors: isCacheValid ttlMs parameter and screen object name conflicts
SKIE doesn't expose Kotlin default parameters to Swift, so isCacheValid calls
need explicit ttlMs argument. Renamed struct-based screen objects to avoid
ambiguity with class-based PageObjects (LoginScreenObject, RegisterScreenObject,
MainTabScreenObject).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 15:59:48 -06:00
Trey t
786a9c6fb6 Merge branch 'codex/uitest' into develop
# Conflicts:
#	iosApp/CaseraTests/TaskMetricsTests.swift
2026-02-24 15:39:33 -06:00
treyt
fc0e0688eb Add comprehensive iOS unit and UI test suites for greenfield test plan
- Create unit tests: DataLayerTests (27 tests for DATA-001–007), DataManagerExtendedTests
  (20 tests for TASK-005, TASK-012, TCOMP-003, THEME-001, QA-002), plus ValidationHelpers,
  TaskMetrics, StringExtensions, DoubleExtensions, DateUtils, DocumentHelpers, ErrorMessageParser
- Create UI tests: AuthenticationTests, PasswordResetTests, OnboardingTests, TaskIntegration,
  ContractorIntegration, ResidenceIntegration, DocumentIntegration, DataLayer, Stability
- Add UI test framework: AuthenticatedTestCase, ScreenObjects, TestFlows, TestAccountManager,
  TestAccountAPIClient, TestDataCleaner, TestDataSeeder
- Add accessibility identifiers to password reset views for UI test support
- Add greenfield test plan CSVs and update automated column for 27 test IDs
- All 297 unit tests pass across 60 suites

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 15:37:56 -06:00
Trey t
2d090f5140 Merge branch 'develop' of github.com:akatreyt/MyCribKMM into develop
# Conflicts:
#	iosApp/CaseraUITests/SimpleLoginTest.swift
#	iosApp/CaseraUITests/Suite0_OnboardingTests.swift
#	iosApp/CaseraUITests/Suite10_ComprehensiveE2ETests.swift
#	iosApp/CaseraUITests/Suite1_RegistrationTests.swift
#	iosApp/CaseraUITests/Suite2_AuthenticationTests.swift
#	iosApp/CaseraUITests/Suite3_ResidenceTests.swift
#	iosApp/CaseraUITests/Suite4_ComprehensiveResidenceTests.swift
#	iosApp/CaseraUITests/Suite5_TaskTests.swift
#	iosApp/CaseraUITests/Suite6_ComprehensiveTaskTests.swift
#	iosApp/CaseraUITests/Suite7_ContractorTests.swift
#	iosApp/CaseraUITests/Suite8_DocumentWarrantyTests.swift
#	iosApp/CaseraUITests/Suite9_IntegrationE2ETests.swift
#	iosApp/CaseraUITests/UITestHelpers.swift
#	iosApp/iosApp/RootView.swift
#	iosApp/iosApp/iOSApp.swift
2026-02-20 10:43:44 -06:00
treyt
fe28034f3d Refactor iOS UI tests to blueprint architecture 2026-02-20 10:38:15 -06:00
treyt
710a8bd1d6 Refactor iOS UI tests to blueprint architecture and migrate legacy suites 2026-02-19 17:30:58 -06:00
Trey t
7d858abf9d Unify sharing codec and wire iOS KMP actuals 2026-02-18 21:37:38 -06:00
Trey t
5e3596db77 Complete re-validation remediation: KMP architecture, iOS platform, XCUITest rewrite
Phases 1-6 of fixes.md — closes all 13 issues from codex_issues_2.md re-validation:

KMP Architecture:
- Fix subscription purchase/restore response contract (VerificationResponse aligned)
- Add feature benefits auth token + APILayer init flow
- Remove ResidenceFormScreen direct API bypass (use APILayer)
- Wire paywall purchase/restore to real SubscriptionApi calls

iOS Platform:
- Add iOS Keychain token storage via Swift KeychainHelper
- Implement Google Sign-In via ASWebAuthenticationSession (GoogleSignInManager)
- DocumentViewModelWrapper observes DataManager for auto-updates
- Add missing accessibility identifiers (document, task columns, Google Sign-In)

XCUITest Rewrite:
- Rewrite test infrastructure: zero sleep() calls, accessibility ID lookups
- Create AuthCriticalPathTests and NavigationCriticalPathTests
- Delete 14 legacy brittle test files (Suite0-10, templates)
- Fix CaseraTests module import (@testable import Casera)

All platforms build clean. TEST BUILD SUCCEEDED.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:50:13 -06:00
Trey t
7444f73b46 Close all 25 codex audit findings across KMP, iOS, and Android
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>
2026-02-18 13:15:34 -06:00
Trey t
ffe5716167 wip 2026-02-18 10:54:25 -06:00
Trey t
2fc4a48fc9 Replace PostHog integration with AnalyticsManager architecture
Remove old PostHogAnalytics singleton and replace with guide-based
two-file architecture: AnalyticsManager (singleton wrapper with super
properties, session replay, opt-out, subscription funnel) and
AnalyticsEvent (type-safe enum with associated values).

Key changes:
- New API key, self-hosted analytics endpoint
- All 19 events ported to type-safe AnalyticsEvent enum
- Screen tracking via AnalyticsManager.Screen enum + SwiftUI modifier
- Remove all identify() calls — fully anonymous analytics
- Add lifecycle hooks: flush on background, update super properties on foreground
- Add privacy opt-out toggle in Settings
- Subscription funnel methods ready for IAP integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 09:48:49 -06:00
Trey t
09be5fa444 Add cancel task confirmation dialog
- Add L10n strings for cancel confirmation
- Add confirmation dialog to ResidenceDetailView
- Fix AllTasksView cancel dialog (was using archive strings)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 10:46:13 -06:00
Trey t
49f4cf168f Simplify task completion animations to 4 celebration types
Keep only implode, firework, starburst, and ripple animations.
Remove slide, fade, scale, flip, bounce, spring, rotation, morph,
confetti, and cascade animations for a more focused experience.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 21:35:42 -06:00
Trey t
3274924937 Add task completion animations and fix 7-day task count
Animation Testing:
- Add AnimationTesting module with 14 animation types for task completion
- Include 4 celebration animations: Implode, Firework, Starburst, Ripple
- Card shrinks, shows checkmark with effect, then moves to next column
- Extended timing (2.2s) for celebration animations

Task Count Fix:
- Fix "7 Days" and "30 Days" counts on residence cards and dashboard
- Previously used API column membership (30-day "due soon" column)
- Now calculates actual days until due from task's effectiveDueDate
- Correctly counts tasks due within 7 days vs 8-30 days

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 21:21:48 -06:00
Trey t
556b187508 Add background task for overnight widget data refresh
- Create BackgroundTaskManager that schedules refresh at random time
  between 12:00 AM - 4:00 AM local time
- Fetches tasks from API, writes to DataManager and shared App Group
- Reloads widget timelines after refresh
- Register task in AppDelegate, schedule when app goes to background
- Add BGTaskSchedulerPermittedIdentifiers and fetch/processing modes to Info.plist

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 20:36:17 -06:00
Trey t
4daaa1f7d8 Consolidate task metrics to single source of truth
- Add API column name constants to WidgetDataManager (overdueColumn,
  dueWithin7DaysColumn, due8To30DaysColumn, etc.)
- Update DataManagerObservable to use WidgetDataManager column constants
- Remove duplicate ResidenceTaskStats struct, use TaskMetrics everywhere
- Delete TaskStatsCalculator.swift (consolidated into WidgetDataManager)
- Rename confusing flags: isUpcoming → isDueWithin7Days, isLater → isDue8To30Days
- Add comprehensive unit tests for TaskMetrics and WidgetTask

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 20:26:52 -06:00
Trey t
cacdf86938 Add ExportOptions.plist for TestFlight automation
Configures automatic App Store Connect upload with:
- app-store-connect distribution method
- Automatic signing
- Symbol upload enabled
- Auto-managed version/build numbers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 18:03:04 -06:00
Trey t
20e79b704f Fix widget overdue count to use kanban categorization
The widget was calculating overdue count from due dates, which didn't
account for in-progress tasks. Now uses the isOverdue flag from kanban
categorization, ensuring the count matches the displayed tasks.

Before: 3 overdue (date-based calc included in-progress tasks)
After: 2 overdue (matches kanban which excludes in-progress)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 17:51:06 -06:00