Expand README with architecture and design rationale - #14
Merged
Conversation
Rewrites the README from a feature checklist into a document that explains why the app is built the way it is: the four-layer feature structure, the Riverpod/go_router/Supabase choices and their trade-offs, the five schema decisions (group_members as the participant identity, RLS as the security boundary, SECURITY DEFINER RPCs where RLS is deliberately narrow, security_invoker views, soft delete), the money rounding rules, and debt simplification. Also corrects details that had drifted from the code: auth is an emailed one-time code rather than a magic link, the project tree listed a supabase/functions directory and a notifications feature folder that do not exist while omitting realtime/ and core/widgets/, setup referenced only 0001_init.sql when there are ten migrations, and the progress checklist marked balances, settle-up, insights, recurring and Android as unbuilt. Genuinely unbuilt work moved to its own section. Em dashes removed throughout. Test count cited in the README verified with flutter test: 58 passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EUD4kp9eThszghQ8MHcoTY
LouisBenjamin
added a commit
that referenced
this pull request
Sep 2, 2026
The README was last expanded in #14, before the statement import feature landed in #15, so it had no mention of the importer at all. - New "Importing a bank statement" feature section - New "Decision: statement import keeps raw data off the server" section covering the privacy boundary, the client-side fingerprint, and the partial unique index - merchant_rules and expenses.source_fingerprint in the data model table - import_expenses() in the RPC list - computeSplits() now noted as shared by three call sites, not two - features/import/, core/dates.dart, docs/statement-import.md in the tree - test count 58 -> 165, plus the import test group - test.yml documented; dropped the stale "tests in CI" gap and added "PDF statement import" to the roadmap - removed no em dashes (there were none); kept the existing voice Claude-Session: https://claude.ai/code/session_01PcEjJSFabfyzty3uUXx6dQ Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rewrites the README from an 88-line feature checklist into a 295-line document that explains the system and the reasoning behind it. Docs only, no code touched.
What's new
ui / providers / data / logic) and the rules that keep it honest, plus why Riverpod (family+autoDispose+ref.invalidateare load-bearing for the realtime channel), why go_router (URLs are part of the web product), and why Supabase with no backend of my own, including the trade-off that business rules end up in SQL and how the Dart/SQL line was drawn.group_membersrather thanprofiles(the decision the rest of the schema hangs off, and what makes guests first-class with noisGuestbranch anywhere), RLS as the security boundary with theSECURITY DEFINERrecursion break, RPCs placed exactly where RLS is deliberately too narrow,security_invoker = trueon views, and soft delete. The migration numbering is read as a record of what went wrong (0002search_path,0003creator select,0005balances view).n-1vsn(n-1)/2.Corrections
The old README had drifted from the code:
signInWithOtp+verifyOTP).supabase/functions/edge functions and afeatures/notifications/folder, neither of which exists, and omittedfeatures/realtime/andcore/widgets/.0001_init.sql; there are ten migrations.Em dashes removed throughout, as requested.
Verification
flutter testrun against this branch: 58 tests, all passing, which is the count cited in the README.flutter pub getleftpubspec.lockunchanged.🤖 Generated with Claude Code
https://claude.ai/code/session_01EUD4kp9eThszghQ8MHcoTY