|
1 | | -# FairShare — Production Launch Notes (March 2026) |
2 | | - |
3 | | -## 1. Overview |
4 | | -FairShare is a pnpm/Turborepo monorepo built for collaborative expense sharing across Expo mobile, NestJS backend, and a Next.js marketing/dashboard experience. The stack is hard‑typed (TypeScript strict), backed by Prisma + Supabase PostgreSQL, Redis caching, and AWS S3 storage. JWT auth, refresh rotation, Google OAuth, and production observability are already wired together. |
5 | | - |
6 | | -## 2. Infrastructure & Deployment |
7 | | -- **Terraform**: reusable modules (`vpc`, `ecs_cluster`, `ecs_service_backend`, `redis`, `s3_storage`, `cloudwatch_logs`) plus per‑env stacks (dev/staging/prod) deploy ECS Fargate backend, ElastiCache Redis, S3 buckets, and CloudWatch log groups. ECS service uses ALB health checks against `/health` and auto scaling (min/max caps). |
8 | | -- **Docker**: multi‑stage backend image with `HEALTHCHECK` hitting `/health`, Prisma migrations bundled, and runtime environment variables wired from `AppConfigService`. |
9 | | -- **CI/CD**: |
10 | | - - `ci.yml`: pnpm + Turbo cache; jobs for typecheck, lint, tests, frontend builds, security audit, dependency review, coverage uploads, and Playwright e2e (guarded by `RUN_E2E`). |
11 | | - - `deploy.yml`: on `main` builds/test -> docker image -> pushes to AWS ECR -> forces ECS service redeploy; image tagged with SHA + `latest`. |
12 | | -- **Scripts**: `pnpm dev`, `pnpm build`, `pnpm test`, `pnpm mobile:build` (EAS production AAB), `pnpm seed`, `pnpm --filter backend prisma:generate`. |
13 | | - |
14 | | -## 3. Backend Implementation |
15 | | -- **Core runtime**: `/api/v1` prefix, global `ValidationPipe`, helmet, compression, CSRF on refresh + `/auth/csrf-token`, and structured request logging (method/path/status/duration plus Prometheus metrics via `observeApiRequest`). AppConfig enforces environment variables for Supabase, Redis, AWS, S3, Stripe, etc. |
16 | | -- **Health, metrics, observability**: `GET /health` reports DB + Redis status, `/metrics` exports Prometheus metrics, and OpenTelemetry NodeSDK auto-instrumentation starts on bootstrap with graceful shutdown. |
17 | | -- **Auth + security**: |
18 | | - - Email/password + Google OAuth, refresh rotation stored hashed, secure `refresh_token` cookie (`httpOnly`, `secure`, `sameSite=strict`). |
19 | | - - `csurf` middleware across refresh endpoints; `AuthController` provides `/csrf-token`. |
20 | | - - Throttler limits auth/login/register to 10 req/min in addition to global 100/min. |
21 | | -- **Payments & settlements**: |
22 | | - - Stripe-based `payments` module creates payment intents, stores idempotency keys, handles webhooks queued via BullMQ, and records settlements (duplicate guard + idempotency). |
23 | | - - Payment webhook job ensures settlement is created once per intent. |
24 | | -- **Jobs + notifications**: |
25 | | - - BullMQ queues for notification delivery, receipt processing, payment webhooks; workers publish Expo push notifications asynchronously (job retry/backoff configured). |
26 | | - - `NotificationsService` now enqueues jobs, reads push tokens from Prisma, and retries chunked Expo requests. |
27 | | -- **Data integrity**: |
28 | | - - Prisma schema now includes `Payment`, `Activity`, `PushToken`, `Balance`, `Settlement`, etc., with indexes and soft delete awareness via `createdAt`. |
29 | | - - Utilities `money.util.ts` and `sanitize.util.ts` ensure BigInt sums and protected text. |
30 | | - - Validation ensures splits add to total, payer/members exist, expenses capped at 1,000,000 cents, settlements prevent duplicates, invites sanitize email, and idempotency key support in payments/settlements. |
31 | | - |
32 | | -## 4. Frontend & UX (priority on polish + flow) |
33 | | -### Mobile Experience |
34 | | -- **Navigation**: auth stack (`Login`, `Register`), main stack with `Dashboard`, tab navigator (`Groups`, `Activity`, `Profile`), and deep links to `GroupDetail`, `GroupMembers`, `AddExpense`, `ExpenseDetail`, `SettleUp`, `Settings`. |
35 | | -- **Dashboard (HomeScreen)**: quick insights, activity preview, quick add expense, quick settle suggestion, and floating action button linking to `AddExpenseScreen`. |
36 | | -- **Group detail**: |
37 | | - - Sections framed by time (`Today`, `This Week`, `Older`) with payer avatars, participant chips, swipe-to-delete (modal confirm), and member avatars that show balance summaries on tap. |
38 | | - - Member roster view with invite-by-email action and inline loading states/empty states backed by themed illustrations (`no-groups`, `no-expenses`, `no-activity`). |
39 | | -- **Add Expense workflow**: |
40 | | - - Real group members loaded, payer + participant selection, split selector supporting equal, exact, and percentage splits with inline validation. |
41 | | - - `SplitSelector` component and shared `split.ts` utility manage calculations; `money` utilities ensure BigInt-friendly arithmetic. |
42 | | -- **Settle Up flow**: |
43 | | - - Greedy simplify data drives buttons; UPI deeplink (`upi://pay?...`) plus “Mark as paid” button after payment ensures manual checkoff; success animation via Lottie. |
44 | | - - Offline + queue backed by `offlineQueue` using NetInfo; API wrappers mark retried POSTs accordingly. |
45 | | -- **Theming & UI polish**: |
46 | | - - Design system with responsive spacing/typography/colors (`#4F46E5`, `#F8FAFC`, Inter), button variants (primary/secondary/danger) with press-scale animation via Reanimated. |
47 | | - - Custom UI primitives (`Avatar`, `Button`, `Card`, `MoneyText`, `LoadingSpinner`, `EmptyState`) built on react-native-paper plus MaterialCommunityIcons. |
48 | | - - Animations for settlements (Lottie), skeleton loaders, haptic feedback, toast system, and offline-safe retry notices. |
49 | | -- **Networking**: |
50 | | - - Axios layer logs requests/responses, attaches JWT, measures latency (`trackApiLatency`), reports high latency to Sentry, and queues POSTs when offline. |
51 | | - - SecureStore persists tokens; Expo Notifications + Sentry SDK initialized in App.tsx; realtime socket handled via `socket.io-client` with rooms by group. |
52 | | - |
53 | | -### Web Experience |
54 | | -- Authenticated dashboard under `/dashboard` showing group list, balances, and recent activity (reuses API contracts). |
55 | | -- Marketing + documentation pages (`/features`, `/pricing`, `/about`, `/login`) include TailwindCSS + Framer Motion cards, hero with CTA, FAQ, newsletter form, and metadata for SEO. |
56 | | - |
57 | | -## 5. Testing & CI |
58 | | -- Backend: Jest suites cover groups, balances, settlements (integration + unit), expenses, simplify, activity, notifications; newly updated mocks support duplicate-guard logic. |
59 | | -- Mobile: jest-expo tests for `SplitSelector`, `AddExpenseScreen`, `GroupListScreen`, `LoginScreen`. |
60 | | -- Playwright e2e: registration → login → group → invite → expense → settlement → activity assertions. |
61 | | -- CI pipeline (see `.github/workflows/ci.yml`) ensures typecheck, lint, tests, builds, security audit, dependency review, coverage artifacts, and Playwright run (conditioned). |
62 | | - |
63 | | -## 6. Logging & Observability |
64 | | -- Backend structured logging (RequestLogger + Sentry + Prometheus). Observability controller exposes metrics for API latency, error count, expense creation, active users. |
65 | | -- Mobile logs prefixed `[api]`, `[auth-ui]`, `[auth]`; Sentry receives high-latency warnings and slow-screen traces. |
66 | | - |
67 | | -## 7. Environment & Secrets |
68 | | -- `.env.example` contains Supabase, JWT secrets, Google OAuth, Redis, CORS, AWS, S3, Stripe, Sentry keys. |
69 | | -- Mobile `.env.example` covers `EXPO_PUBLIC_API_URL`, Sentry, and S3 base URL. |
70 | | -- `AppConfigService` enforces `mustGet` for mandatory vars, while mobile/respective services resolve host addresses for Expo Go vs LAN dev. |
71 | | - |
72 | | -## 8. Next Steps |
73 | | -1. Wire Expo notification tokens to backend + real push service (currently logged through Expo queue). |
74 | | -2. Migrate AWS SDK usage to v3 and align Terraform CDK if needed. |
75 | | -3. Document E2E setup (`RUN_E2E=true`) and release Playwright builds in CI. |
| 1 | +# FairShare Project Status |
| 2 | + |
| 3 | +Last updated: March 12, 2026 |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +FairShare is a monorepo expense-sharing application with: |
| 8 | + |
| 9 | +- A NestJS backend in `apps/backend` |
| 10 | +- An Expo React Native mobile app in `apps/mobile` |
| 11 | +- A web app workspace in `apps/web` |
| 12 | +- Shared TypeScript contracts in `@fairshare/shared-types` |
| 13 | + |
| 14 | +The project is beyond bootstrap stage. Core expense-sharing flows, settlements, notifications, receipts, realtime updates, and payment intent creation are implemented. Recent work has shifted toward reliability, idempotency, delivery safety, and production hardening. |
| 15 | + |
| 16 | +## Infrastructure And Deployment |
| 17 | + |
| 18 | +- Monorepo managed with `pnpm` and Turbo |
| 19 | +- PostgreSQL accessed through Prisma |
| 20 | +- Redis used for cache invalidation and queue-related workflows |
| 21 | +- Socket.IO used for realtime updates |
| 22 | +- S3 integration present for receipt flows using AWS SDK v3 presigning |
| 23 | +- Stripe integration present for payment intents and webhooks |
| 24 | +- Sentry and OpenTelemetry hooks present in the backend |
| 25 | + |
| 26 | +Backend runtime characteristics: |
| 27 | + |
| 28 | +- Nest listens on `0.0.0.0` |
| 29 | +- Global API prefix is `/api/v1` |
| 30 | +- CORS is enabled from configured origins |
| 31 | +- Throttling, compression, helmet, cookie parsing, CSRF protection, and request logging are enabled |
| 32 | + |
| 33 | +## Backend Implementation |
| 34 | + |
| 35 | +### Implemented modules |
| 36 | + |
| 37 | +The backend currently wires these major modules: |
| 38 | + |
| 39 | +- Auth |
| 40 | +- Users |
| 41 | +- Groups |
| 42 | +- Expenses |
| 43 | +- Balances |
| 44 | +- Settlements |
| 45 | +- Simplify |
| 46 | +- Receipts |
| 47 | +- Notifications |
| 48 | +- Payments |
| 49 | +- Jobs |
| 50 | +- Activity |
| 51 | +- Realtime |
| 52 | +- Health |
| 53 | +- Observability |
| 54 | +- Redis |
| 55 | +- S3 |
| 56 | +- Prisma |
| 57 | + |
| 58 | +### Implemented backend capabilities |
| 59 | + |
| 60 | +- User authentication and token-based login flows |
| 61 | +- Group creation and membership management |
| 62 | +- Expense creation, listing, update, deletion, and detail retrieval |
| 63 | +- Balance tracking and debt simplification support |
| 64 | +- Settlement creation between group members |
| 65 | +- Receipt upload URL generation |
| 66 | +- Activity logging for domain actions |
| 67 | +- Push token registration and notification delivery workflows |
| 68 | +- Stripe payment intent creation |
| 69 | +- Payment webhook handling that records successful payments as settlements |
| 70 | +- Realtime emission for group activity |
| 71 | +- Health and metrics endpoints |
| 72 | + |
| 73 | +### Recent backend fix |
| 74 | + |
| 75 | +A NestJS startup failure caused by a module cycle was resolved. |
| 76 | + |
| 77 | +Problem chain: |
| 78 | + |
| 79 | +- `SettlementsModule -> NotificationsModule -> JobsModule -> PaymentsModule -> SettlementsModule` |
| 80 | + |
| 81 | +Resolution: |
| 82 | + |
| 83 | +- `SettlementsModule` now uses `forwardRef(() => NotificationsModule)` so Nest can resolve the cycle during module initialization |
| 84 | + |
| 85 | +This restored a clean backend boot path. |
| 86 | + |
| 87 | +### Recent backend reliability work |
| 88 | + |
| 89 | +Additional backend hardening completed in the latest pass: |
| 90 | + |
| 91 | +- Migrated S3 presigned upload generation from AWS SDK v2 to AWS SDK v3 |
| 92 | +- Added receipt upload URL coverage with service-level and HTTP-level tests |
| 93 | +- Hardened payment webhook processing so settlement creation happens before payment status is marked `succeeded` |
| 94 | +- Improved settlement idempotency handling for duplicate webhook delivery and unique-key races |
| 95 | +- Enforced Stripe signature presence when a webhook secret is configured |
| 96 | +- Added notification delivery retry backoff and automatic cleanup of invalid Expo push tokens |
| 97 | + |
| 98 | +## Frontend And UX |
| 99 | + |
| 100 | +### Mobile status |
| 101 | + |
| 102 | +The Expo mobile app already includes: |
| 103 | + |
| 104 | +- Login and registration |
| 105 | +- Group list and group detail flows |
| 106 | +- Group members view |
| 107 | +- Add expense and expense detail flows |
| 108 | +- Settlement flow |
| 109 | +- Activity screen |
| 110 | +- Profile and settings screens |
| 111 | +- Shared UI components for cards, buttons, avatars, skeleton states, empty states, and toasts |
| 112 | +- Zustand-based stores for auth, groups, expenses, and toast state |
| 113 | +- Service clients for auth, groups, expenses, settlements, realtime, and users |
| 114 | + |
| 115 | +Implemented mobile platform features: |
| 116 | + |
| 117 | +- API client with request logging and latency tracking |
| 118 | +- Bearer-token injection from secure storage |
| 119 | +- Realtime connection after authentication |
| 120 | +- Push token registration through `expo-notifications` |
| 121 | +- Offline POST queueing for selected write actions |
| 122 | + |
| 123 | +### Recent mobile fixes |
| 124 | + |
| 125 | +Recent development fixes addressed local runtime issues: |
| 126 | + |
| 127 | +- Removed the stale `apps/mobile/.env` override for `EXPO_PUBLIC_API_URL` |
| 128 | +- Stopped forcing the dead API host `http://10.111.154.142:3001/api/v1` |
| 129 | +- Restored local API host auto-detection from the Expo runtime host |
| 130 | +- Removed the `api.ts` <-> `offlineQueue.ts` require cycle |
| 131 | +- Refactored the offline queue so it receives a request executor from `api.ts` instead of importing the API client directly |
| 132 | + |
| 133 | +This makes local mobile networking more reliable as long as the device and backend machine are on the same reachable network. |
| 134 | + |
| 135 | +### Web status |
| 136 | + |
| 137 | +The web workspace exists in the monorepo, but backend and mobile appear to be the most actively implemented parts of the product at this stage. Web should be treated as secondary until a dedicated milestone or readiness target is documented. |
| 138 | + |
| 139 | +## Testing And CI |
| 140 | + |
| 141 | +Repository-level scripts include: |
| 142 | + |
| 143 | +- `pnpm lint` |
| 144 | +- `pnpm test` |
| 145 | +- `pnpm e2e` |
| 146 | + |
| 147 | +Recent validation used during current fixes: |
| 148 | + |
| 149 | +- `pnpm --filter backend lint` |
| 150 | +- `pnpm --filter backend build` |
| 151 | +- `pnpm --filter backend test -- receipts` |
| 152 | +- `pnpm --filter backend test -- payments settlements` |
| 153 | +- `pnpm --filter backend test -- notifications` |
| 154 | +- `pnpm --filter mobile exec tsc --noEmit` |
| 155 | + |
| 156 | +There are tests in both backend and mobile codebases. The latest backend pass added direct coverage for receipt URL generation, payment webhook idempotency, settlement idempotency behavior, and notification retry handling. |
| 157 | + |
| 158 | +## Logging And Observability |
| 159 | + |
| 160 | +Backend observability already includes: |
| 161 | + |
| 162 | +- Sentry initialization |
| 163 | +- OpenTelemetry startup and shutdown hooks |
| 164 | +- Request logging middleware |
| 165 | +- Domain logging around notifications and payments |
| 166 | +- Prometheus-style metrics infrastructure through `prom-client` |
| 167 | + |
| 168 | +Mobile development diagnostics currently include: |
| 169 | + |
| 170 | +- API base URL logging in development |
| 171 | +- Request, response, and error logging in the API client |
| 172 | +- API latency tracking |
| 173 | + |
| 174 | +## Environment And Secrets |
| 175 | + |
| 176 | +Backend environment configuration currently covers: |
| 177 | + |
| 178 | +- Port |
| 179 | +- CORS origins |
| 180 | +- Redis connection |
| 181 | +- PostgreSQL and Prisma access |
| 182 | +- Stripe secret and webhook configuration |
| 183 | +- S3 configuration |
| 184 | +- Sentry DSN |
| 185 | + |
| 186 | +Mobile environment configuration currently covers: |
| 187 | + |
| 188 | +- Optional `EXPO_PUBLIC_API_URL` override |
| 189 | +- Optional `EXPO_PUBLIC_SENTRY_DSN` |
| 190 | + |
| 191 | +Important local mobile networking behavior: |
| 192 | + |
| 193 | +- If `EXPO_PUBLIC_API_URL` is set, it overrides host auto-detection |
| 194 | +- If it is not set, the app derives the backend host from the Expo runtime host during local development |
| 195 | +- The phone or emulator and the backend machine must still be on the same reachable network |
| 196 | + |
| 197 | +## Current Status |
| 198 | + |
| 199 | +### Working now |
| 200 | + |
| 201 | +- Backend boots successfully |
| 202 | +- Core API surface for auth, groups, expenses, balances, settlements, receipts, notifications, payments, and activity is implemented |
| 203 | +- Prisma, Redis, realtime, and payment flows are integrated in the backend |
| 204 | +- Receipt upload URLs are generated through AWS SDK v3 presigning |
| 205 | +- Payment webhook settlement handling is idempotent at the settlement layer and safer under retry |
| 206 | +- Invalid Expo push tokens are removed automatically after permanent delivery failures |
| 207 | +- Mobile app can authenticate, navigate the core flows, register push tokens, connect to realtime, and use the offline queue |
| 208 | + |
| 209 | +### Partially complete |
| 210 | + |
| 211 | +- Push notifications are implemented, but full remote notification testing should use a development build instead of Expo Go |
| 212 | +- Payments are implemented at the intent and webhook level, with improved idempotency, but still need broader production validation |
| 213 | +- Web progress is less clearly advanced than backend and mobile |
| 214 | + |
| 215 | +## Known Gaps |
| 216 | + |
| 217 | +- Expo package versions are slightly out of sync with the installed SDK and still produce compatibility warnings |
| 218 | +- `expo-notifications` remote push support is limited in Expo Go |
| 219 | +- Local mobile networking remains environment-sensitive when LAN addressing changes |
| 220 | +- Receipt OCR and structured receipt parsing are not implemented yet |
| 221 | +- Smart split suggestion APIs and UI are not implemented yet |
| 222 | +- Mobile notification center and expanded offline retry UI are not implemented yet |
| 223 | +- Broader observability counters and tracing for expense, settlement, and webhook flows still need expansion |
| 224 | + |
| 225 | +## Next Steps |
| 226 | + |
| 227 | +1. Align Expo package versions with the installed SDK. |
| 228 | +2. Validate login, expense, settlement, payment, and notification flows end to end on a real device and a development build. |
| 229 | +3. Add receipt OCR processing and structured receipt item storage. |
| 230 | +4. Add smart split suggestion APIs and mobile UI. |
| 231 | +5. Expand observability counters and tracing for expense creation, settlement creation, and webhook processing. |
| 232 | +6. Clarify the target scope and milestone for the web workspace. |
0 commit comments