Skip to content

Commit 0ee64c4

Browse files
committed
Add audits, integration tests, bootstrap & theme
Add QA artifacts and integration tooling, refactor bootstrap and theming, and apply various runtime and CI fixes. This commit introduces two audit reports (FRESH_CODEBASE_AND_UI_REVIEW.md, QA_UX_Audit_Report.md), integration tests and driver entries (integration_test/*, test_driver/*), and a dart_define example. Core app changes: refactor bootstrap into a Notifier-based bootstrapProvider with serialized data hydration and explicit syncAllData, add ThemeNotifier/persistent themeProvider and wire theme selection into main, add lifecycle resume sync, and make main compatible with integration/driver bindings and safer Supabase initialization via assertValidReleaseSupabaseConfig and dart-define URLs. Controller tweaks: auth timeouts and session fallbacks, health error clearing on load, remove duplicate client-side notification sends in chat/match controllers (moved to DB triggers), and notification controller listener pre-seed fix. Project and CI updates: added many Supabase migration and policy files, updated supabase table/storage policies, updated ios-build workflow to inject SUPABASE_* dart-defines and include secrets, updated .gitignore and android/gradle.properties optimizations, and small emulator script PATH fixes. Misc: new pet model fields and multiple view/controller UI/accessibility changes referenced by the audits.
1 parent 47a8b78 commit 0ee64c4

47 files changed

Lines changed: 2588 additions & 802 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/android-emulator-skill/scripts/emu_health_check.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
`<#
1+
<#
22
.SYNOPSIS
33
Android Emulator Testing Environment Health Check
44
@@ -109,7 +109,7 @@ if (Get-Command adb -ErrorAction SilentlyContinue) {
109109
if (-not [string]::IsNullOrWhiteSpace($env:ANDROID_HOME)) {
110110
$platformToolsPath = Join-Path $env:ANDROID_HOME 'platform-tools'
111111
if ((Test-Path (Join-Path $platformToolsPath 'adb.exe')) -or (Test-Path (Join-Path $platformToolsPath 'adb'))) {
112-
$env:PATH += ";$platformToolsPath"
112+
$env:PATH = $env:PATH + ';' + $platformToolsPath
113113
Check-Warning "ADB found in SDK but not in PATH. Adding it temporarily."
114114
Check-Passed "ADB is installed"
115115
} else {
@@ -138,7 +138,7 @@ if (Get-Command emulator -ErrorAction SilentlyContinue) {
138138
if (-not [string]::IsNullOrWhiteSpace($env:ANDROID_HOME)) {
139139
$emulatorPath = Join-Path $env:ANDROID_HOME 'emulator'
140140
if ((Test-Path (Join-Path $emulatorPath 'emulator.exe')) -or (Test-Path (Join-Path $emulatorPath 'emulator'))) {
141-
$env:PATH += ";$emulatorPath"
141+
$env:PATH = $env:PATH + ';' + $emulatorPath
142142
Check-Warning "Emulator found in SDK but not in PATH. Adding it temporarily."
143143
Check-Passed "Emulator is installed"
144144
} else {

.github/workflows/ios-build.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ jobs:
3737
build:
3838
runs-on: macos-latest
3939
timeout-minutes: 30
40+
env:
41+
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
42+
SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
4043

4144
steps:
4245
- name: Checkout repository
@@ -195,7 +198,9 @@ jobs:
195198
flutter build ios --no-codesign --simulator
196199
else
197200
echo "Building Flutter iOS Release..."
198-
flutter build ios --release --no-codesign
201+
flutter build ios --release --no-codesign \
202+
--dart-define=SUPABASE_URL="$SUPABASE_URL" \
203+
--dart-define=SUPABASE_ANON_KEY="$SUPABASE_ANON_KEY"
199204
fi
200205
cd "$IOS_PATH"
201206
elif [ "$PROJECT_TYPE" = "reactnative" ] || [ "$PROJECT_TYPE" = "expo" ]; then

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ migrate_working_dir/
3232
.pub/
3333
/build/
3434
/coverage/
35+
config/dart_define.json
3536

3637
# Symbolication related
3738
app.*.symbols

FRESH_CODEBASE_AND_UI_REVIEW.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# PetSphere: Comprehensive Codebase & UI/UX Review (Deep Dive)
2+
3+
**Date**: May 2, 2026
4+
**Scope**: Complete Codebase Architecture, Supabase Backend, Multi-platform (Android, iOS, Web) setup, Detailed UI/UX Review, Security, and Best Practices.
5+
6+
## Executive Summary
7+
PetSphere is an extremely feature-rich Flutter application that merges a pet social network, a pet-care/health tracker, a dating/matching app for pets, and an e-commerce marketplace into a single cohesive platform.
8+
9+
This deep-dive review audits every layer of the application: the Riverpod state management, Supabase integration, multi-platform configurations, and the UI/UX implementation. While the architecture (Controller-Repository-Model) is robust, the UI layer suffers from the "Massive Widget" anti-pattern. There are also specific security vulnerabilities related to error handling that need immediate remediation.
10+
11+
---
12+
13+
## 1. Multi-Platform Configurations (Android, iOS, Web)
14+
15+
The codebase supports three primary targets: Android, iOS, and Web.
16+
- **Android**: Configuration resides in `android/app/src/main/kotlin/com/petdatingapp/app/`. The unique `applicationId` and `namespace` is correctly configured as `com.petdatingapp.app`.
17+
- **iOS**: Configuration uses the `PRODUCT_BUNDLE_IDENTIFIER` set to `com.petdatingapp.app`.
18+
- **Web**: Standard Flutter web configuration with index.html. Given the heavily app-centric features (matching, gamification, local health tracking), the web build will serve primarily as a responsive PWA.
19+
**Issue**: Web target may experience performance hits with large lists (e.g., social feeds, chat) without proper lazy loading and image optimization.
20+
21+
---
22+
23+
## 2. Architecture & State Deep Dive
24+
25+
The app strictly follows a **Controller-Repository-Model** pattern.
26+
27+
### 2.1 State Management (Controllers)
28+
State is managed via `flutter_riverpod`. The Notifiers (`lib/controllers/`) orchestrate business logic and hold UI state, abstracting the repositories from the views.
29+
- **Auth State**: `auth_controller.dart` manages `AuthStatus` (initial, unauthenticated, authenticated).
30+
- **Social Feed**: `feed_controller.dart`
31+
- **Pet Management & Health**: `pet_controller.dart`, `health_controller.dart`, `pet_care_controller.dart`, `pet_expense_controller.dart`. Manage state for pets, their AI plans, vet appointments, vaccinations, and daily logs.
32+
- **Matching & Chat**: `match_controller.dart`, `chat_controller.dart`. Handles dating logic and real-time messaging.
33+
- **Marketplace**: `marketplace_controller.dart`, `cart_controller.dart`.
34+
- **Others**: `bootstrap_controller.dart` (startup hydration), `follow_controller.dart`, `notification_controller.dart`, `search_controller.dart`.
35+
36+
### 2.2 Data Layer (Repositories & Models)
37+
- **Repositories** (`lib/repositories/`): These classes handle 100% of the Supabase API calls. Examples include `auth_repository.dart`, `chat_repository.dart`, `health_repository.dart`, `pet_care_repository.dart`. They are injected via Riverpod `Provider`s, making them highly testable.
38+
- **Models** (`lib/models/`): Over 17 strongly-typed models (e.g., `user_model.dart`, `pet_health_models.dart`, `product_model.dart`) ensure type safety across the app.
39+
40+
---
41+
42+
## 3. Supabase Backend Analysis (Local & Remote)
43+
44+
### Database Schema (Public)
45+
The Postgres 17 database is massive and well-structured:
46+
- **Core**: `profiles`, `pets`
47+
- **Social**: `posts`, `post_likes`, `comments`, `stories`, `follows`
48+
- **Matching/Chat**: `match_requests`, `matches`, `chat_threads`, `messages`
49+
- **Marketplace**: `products`, `orders`, `order_items`
50+
- **Health/Care**: `pet_care_logs`, `pet_weight_logs`, `pet_vet_appointments`, `pet_vaccinations`, `pet_symptoms`, `pet_medications`, `pet_medication_doses`, `pet_allergies`, `pet_parasite_prevention`, `pet_dental_logs`
51+
- **Gamification**: `pet_care_gamification`, `care_badge_definitions`, `pet_care_badge_unlocks`
52+
53+
### Backend Security
54+
- **Row Level Security (RLS)**: Enabled across all `public` tables. This is an excellent security measure ensuring users can only read/write their own data.
55+
- **Edge Functions**: Features `ai-pet-care-plan` and `moderate-content`. Both functions have `verify_jwt: true`, which is the correct best practice for securing serverless functions.
56+
57+
---
58+
59+
## 4. Security & Authentication Audit
60+
61+
- **Authentication**: `auth_repository.dart` correctly utilizes `supabase.auth.signInWithPassword` and `signUp`.
62+
- **UUID Validation**: The app uses `isValidUuid` (in `lib/utils/validation_utils.dart`) to sanitize DB inputs and routing parameters.
63+
- **VULNERABILITY - Raw Exception Exposure**:
64+
- **Location**: `lib/views/login_screen.dart` (and likely others).
65+
- **Details**: When an exception occurs, the app uses `ScaffoldMessenger` to show `Text('Error: ${e.toString()}')`.
66+
- **Risk**: This leaks raw Supabase/Postgres errors to the end-user. It can reveal database schema details or connection strings if not handled by the client library properly.
67+
- **Fix**: Catch specific exceptions and return generic, user-friendly strings (e.g., "Invalid email or password").
68+
69+
---
70+
71+
## 5. Comprehensive Feature & UI/UX Audit
72+
73+
### Design System & Theming
74+
- **Theming**: Configured in `lib/theme/app_theme_v2_material3.dart`. It implements a comprehensive Material 3 design system, centralizing design tokens efficiently.
75+
- **Accessibility Flaw**: The app is hardcoded to `ThemeMode.dark` in `main.dart`. It completely lacks a Light Mode, which severely impacts accessibility for users with astigmatism or reading difficulties in bright environments.
76+
77+
### Screen & Component Analysis
78+
The app contains over 30 massive screens in `lib/views/`, covering:
79+
- **Social**: `home_screen.dart`, `create_post_screen.dart`, `create_story_screen.dart`, `discovery_screen.dart`.
80+
- **Matching/Chat**: `liked_pets_screen.dart`, `messages_list_screen.dart`, `chat_screen.dart`.
81+
- **Marketplace**: `marketplace_screen.dart`, `cart_screen.dart`, `order_history_screen.dart`.
82+
- **Health/Care**: `health_tab.dart`, `pet_care_screen.dart`, `vet_booking_screen.dart`, `emergency_care_screen.dart`, `pet_health_record_screen.dart`.
83+
- **Gamification**: `gamification_screen.dart`.
84+
- **Misc Utilities**: `adoption_center_screen.dart`, `community_groups_screen.dart`, `lost_and_found_screen.dart`, `pet_breed_identifier_screen.dart`, `pet_expense_tracker_screen.dart`, `pet_memorial_screen.dart`, etc.
85+
86+
### UI/UX Issues Identified
87+
1. **"Massive Widget" Anti-Pattern**:
88+
- `health_tab.dart` (88KB)
89+
- `pet_care_screen.dart` (55KB)
90+
- `discovery_screen.dart` (53KB)
91+
- `create_post_screen.dart` (44KB)
92+
- *Impact*: These files are impossibly difficult to maintain. They violate the project's coding convention.
93+
- *Solution*: Extract complex `build` method logic into private helper methods (`_buildHeader()`, etc.) and break large sections into reusable components in `lib/views/components/`.
94+
2. **Missing Loading States/Skeleton Loaders**: With extensive remote data fetching, relying solely on `CircularProgressIndicator` creates a jarring UX.
95+
3. **Deep Linking Complexity**: Given the high volume of screens, GoRouter handles routing, but passing complex objects via `extra` instead of ID-based parameters might cause state inconsistencies.
96+
97+
---
98+
99+
## 6. Best Practices & Recommendations (Flutter + Supabase)
100+
101+
Based on industry standards and Supabase/Flutter documentation:
102+
103+
1. **State & Environment Testing**:
104+
- *Recommendation*: Use `ProviderContainer` to override repository providers with `Fake` repositories (e.g., `FakePetRepository`) for unit tests. Avoid mock libraries like `mockito` to prevent environment flakiness.
105+
2. **Global Exception Handling**:
106+
- *Recommendation*: Introduce an `AppException` class. Repositories should catch `PostgrestException` or `AuthException` and throw `AppException` with safe, generic messages. The UI should only ever display `AppException.message`.
107+
3. **Supabase Realtime Subscriptions**:
108+
- *Recommendation*: Ensure all `supabase.channel().on(...)` subscriptions are properly disposed of in `dispose()` methods or managed via Riverpod `ref.onDispose` to prevent memory leaks in Chat and Notification features.
109+
4. **Network Resilience**:
110+
- *Recommendation*: When listening to `supabase.auth.onAuthStateChange`, implement the `onError` callback. If the network drops, Supabase throws an error on this stream. Unhandled, it will crash the app.
111+
5. **Optimize "Build" Methods**:
112+
- *Recommendation*: Adhere to the established coding convention. Move complex widgets like `post_card.dart` into granular private methods or separate stateless widgets to prevent unnecessary rebuilds of the entire tree.
113+
6. **Implement ThemeMode.system**:
114+
- *Recommendation*: Remove the hardcoded `ThemeMode.dark` and implement a corresponding Light Theme to support system preferences.
115+
116+
---
117+
*End of Report*

QA_UX_Audit_Report.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# PetSphere QA / UX Accessibility Audit
2+
3+
**Report ID:** PS-QA-2026-05-03
4+
**Auditor role:** QA Automation + UI/UX (autonomous tooling)
5+
**App package:** `com.example.pet_dating_app` (PetSphere debug build)
6+
**Incremental log:** This file is updated during the audit run; later phases may be extended after a confirmed login.
7+
8+
---
9+
10+
## 0. Environment & tooling reality check
11+
12+
| Item | Result |
13+
|------|--------|
14+
| **ADB devices** | Only `emulator-5554` was attached. **No wireless/physical device serial appeared** in `adb devices -l`. All steps below ran on this emulator unless you reconnect the wireless device. |
15+
| **App install** | Initial state had **no installed package** for PetSphere on the emulator. A **debug APK** was built (`flutter build apk --debug`) and installed with `adb install -r`. |
16+
| **Automation stack** | `uiautomator dump` + repo skill script `screen_mapper.py` (`.claude/skills/android-emulator-skill/scripts`). |
17+
| **Credentials** | Sign-in was attempted with the stakeholder-supplied test account. **The password is not copied into this report.** Because the password was shared in chat, **rotate it if this workspace or logs could be shared.** |
18+
19+
### Flutter + UIAutomator caveat (critical)
20+
21+
Flutter renders to a canvas; the Android accessibility bridge maps a **semantics tree** into `EditText` / `Button` nodes. When dumps are empty or nearly empty, **do not guess coordinates**: enable semantics debugging or add `Semantics` (see [Flutter accessibility widgets](https://docs.flutter.dev/development/ui/widgets/accessibility)). Known gaps exist for `TextField` `content-desc` in some versions (e.g. [flutter#153495](https://github.com/flutter/flutter/issues/153495)).
22+
23+
---
24+
25+
## Phase 1 — Authentication & baseline
26+
27+
### Screen: **Login / welcome**
28+
29+
**Accessibility / semantics status**
30+
31+
- **Partially exposed:** Native nodes present (`android.widget.EditText` ×2, buttons with `content-desc`: `Sign In`, `Forgot Password?`, etc.).
32+
- **Gaps identified:**
33+
- **Email `EditText`** surfaced the **typed email as plain `text` in the UIAutomator XML** (visible to dumps and hybrid automation). This is expected for non-obscured fields but is a **privacy consideration** for screen recording and shared logs.
34+
- **Password field** showed **replacement characters / mojibake** in the dump (obscured text pipeline), which breaks **reliable textual validation** of entry via XML alone.
35+
- `content-desc` on the two `EditText` nodes was **empty** in captured dumps; identification relied on order and bounds.
36+
37+
**Available actions identified (UIAutomator)**
38+
39+
- Enter email and password, **Sign In**, **Forgot Password?**, **Register**, **Google**, **Apple**, scrollable marketing copy (**Welcome Back**, **PetSphere** branding).
40+
41+
**Test cases executed**
42+
43+
- Launch: `am start -n com.example.pet_dating_app/.MainActivity`
44+
- **Data:** Stakeholder email `afsanchowdhury25@gmail.com`; password supplied out-of-band (not logged here). Entry used `adb shell input text` plus `keyevent 77` for `@`.
45+
46+
**Issues / errors**
47+
48+
- **P1 — Home baseline not reached:** After **Sign In** taps (center of button bounds), the hierarchy **remained on the login screen** (`Welcome Back`, `Sign In` still present). Possible causes: wrong credentials for this Supabase project, network/auth error not surfaced in the automation capture, IME/focus so password never committed, or loading state not waited long enough.
49+
- **P2 — Automation fragility:** Coordinate-based ADB typing is brittle for Flutter fields; **password obscuring** complicates XML verification.
50+
- **P3 — Device mismatch:** Instructions assumed a **wireless physical device**; only an **emulator** was available in this session.
51+
52+
**Proposed fixes & best practices (with research)**
53+
54+
1. **Semantics for forms:** Wrap critical fields with explicit `Semantics` (`label`, `textField`, `obscured` for password) so TalkBack / automation trees are stable; align with [SemanticsProperties](https://docs.flutter.dev/flutter/semantics/SemanticsProperties-class.html).
55+
- **Code change applied in-repo:** `lib/views/login_screen.dart` now wraps email/password `TextFormField`s in `Semantics` with labels **Email address** and **Password** (and `obscured: true` on the password semantics). Rebuild the APK to validate improved dumps.
56+
2. **Preferred automated auth:** Use **`integration_test`** + `WidgetTester.enterText` and `Key('login_email_field')` / `Key('login_password_field')` (already present) instead of raw `input text` for real credentials ([Flutter integration testing](https://docs.flutter.dev/testing/integration-tests)).
57+
3. **Material 3 / forms:** Keep **visible labels**, **clear validation**, and **error region** semantics; ensure loading states expose `Semantics` (e.g. announcing progress) per Material accessibility guidance.
58+
59+
**Feature improvements**
60+
61+
- Surface **inline auth failure messages** in a semantics-friendly region (live region) when Supabase rejects credentials.
62+
- Consider **biometric / token** dev-only bypass for QA builds (guarded by flavor) to unblock full navigation audits without storing passwords in scripts.
63+
64+
---
65+
66+
### Screen: **Home (Atelier feed)***baseline not captured*
67+
68+
**Status:** **Blocked** pending successful authentication. No `Atelier` / bottom-nav semantics (`Home`, `Discover`, …) appeared in post-login dumps in this session.
69+
70+
**Planned sequence when unblocked (Phase 2 template)**
71+
72+
For **each** screen, the following will be executed:
73+
74+
1. Scroll to bottom (lazy load).
75+
2. Dump UI tree; list clickable elements.
76+
3. Execute each action with pet-care realistic data.
77+
4. Check errors, loaders, overflows.
78+
5. Navigate back without loops.
79+
80+
---
81+
82+
## Phase 2 — Screen-by-screen
83+
84+
| Screen | Status |
85+
|--------|--------|
86+
| Home / feed | **Reached** (emulator). UI shows **Atelier** title, **Search** AppBar actions, **Retry** on feed error. UIAutomator dump exposed `content-desc="Home"` / `Discover` on bottom nav. DB error surfaced in semantics: Postgrest **infinite recursion** on `pets` RLS (42P17). |
87+
| Discover | Bottom tab present; deep dive pending |
88+
| Pet care hub | Not exercised |
89+
| Marketplace | Not exercised |
90+
| Profile | Not exercised |
91+
| Search / notifications / messages from home AppBar | Semantics present (`Search`, etc.) |
92+
93+
**Flutter Driver (Phase 1 journey):** `flutter drive` test passes when the test body runs inside **`driver.runUnsynchronized`**. Default frame sync waits until **no transient callbacks**; splash/home **`CircularProgressIndicator`** keeps callbacks active, so `waitFor` / `tap` never complete. Shell is asserted with **`find.text('Atelier')`** and **`find.byTooltip('Search')`**; bottom **Discover** tab uses **`find.byValueKey('bottom_nav_1')`** (`main_layout.dart`).
94+
95+
**Note:** Bottom nav items now have stable **`ValueKey('bottom_nav_$index')`** plus **`bottom_nav_pet_care`** for the center FAB.
96+
97+
---
98+
99+
## Phase 3 — Consolidated recommendations
100+
101+
1. **Reconnect the physical wireless device** and re-run `adb devices`; update this report with the real serial.
102+
2. **Rebuild & reinstall** after the login `Semantics` change; re-dump login XML and confirm `content-desc` / node labels for both fields.
103+
3. **Confirm Supabase user** exists for the test email in the **same project** as the app’s `supabaseInitUrl` / anon key (debug vs release defines).
104+
4. For **full Phase 2**, either: fix auth for the test account, or use a **QA-only service role / test user seed** (policy-compliant) plus `integration_test`.
105+
5. Optional dev aid: temporary **`MaterialApp.router(..., showSemanticsDebugger: true)`** in debug builds to visualize semantics during audits (remove before store).
106+
107+
---
108+
109+
## References (external)
110+
111+
- [Flutter — Accessibility widgets](https://docs.flutter.dev/development/ui/widgets/accessibility)
112+
- [Flutter API — SemanticsProperties](https://docs.flutter.dev/flutter/semantics/SemanticsProperties-class.html)
113+
- [GitHub — TextField / UIAutomator content description discussion](https://github.com/flutter/flutter/issues/153495)
114+
- [Flutter — Integration tests](https://docs.flutter.dev/testing/integration-tests)
115+
116+
---
117+
118+
## Changelog
119+
120+
| Time (UTC) | Update |
121+
|------------|--------|
122+
| 2026-05-03 | Initial environment check; APK install; login screen mapped; sign-in blocked at home; login Semantics patch landed in `login_screen.dart`; wireless device not present in `adb devices`. |
123+
| 2026-05-03 | Driver test green: `runUnsynchronized` + `Atelier`/`Search` finders + nav `ValueKey`s; `auth_controller` cold-start profile fetch timeout (15s) to avoid stuck splash if `profiles` hangs; QA: fix `pets` RLS recursion. |

android/.kotlin/sessions/kotlin-compiler-4306309977914915476.salive

Whitespace-only changes.

0 commit comments

Comments
 (0)