* OAuth * Add API test routes and update Doorkeeper token handling for test environment - Introduced API namespace with test routes for controller testing in the test environment. - Updated Doorkeeper configuration to allow fallback to plain tokens in the test environment for easier testing. - Modified schema to change resource_owner_id type from bigint to string. * Implement API key authentication and enhance access control - Replaced Doorkeeper OAuth authentication with a custom method supporting both OAuth and API keys in the BaseController. - Added methods for API key authentication, including validation and logging. - Introduced scope-based authorization for API keys in the TestController. - Updated routes to include API key management endpoints. - Enhanced logging for API access to include authentication method details. - Added tests for API key functionality, including validation, scope checks, and access control enforcement. * Add API key rate limiting and usage tracking - Implemented rate limiting for API key authentication in BaseController. - Added methods to check rate limits, render appropriate responses, and include rate limit headers in responses. - Updated routes to include a new usage resource for tracking API usage. - Enhanced tests to verify rate limit functionality, including exceeding limits and per-key tracking. - Cleaned up Redis data in tests to ensure isolation between test cases. * Add Jbuilder for JSON rendering and refactor AccountsController - Added Jbuilder gem for improved JSON response handling. - Refactored index action in AccountsController to utilize Jbuilder for rendering JSON. - Removed manual serialization of accounts and streamlined response structure. - Implemented a before_action in BaseController to enforce JSON format for all API requests. * Add transactions resource to API routes - Added routes for transactions, allowing index, show, create, update, and destroy actions. - This enhancement supports comprehensive transaction management within the API. * Enhance API authentication and onboarding handling - Updated BaseController to skip onboarding requirements for API endpoints and added manual token verification for OAuth authentication. - Improved error handling and logging for invalid access tokens. - Introduced a method to set up the current context for API requests, ensuring compatibility with session-like behavior. - Excluded API paths from onboarding redirects in the Onboardable concern. - Updated database schema to change resource_owner_id type from bigint to string for OAuth access grants. * Fix rubocop offenses - Fix indentation and spacing issues - Convert single quotes to double quotes - Add spaces inside array brackets - Fix comment alignment - Add missing trailing newlines - Correct else/end alignment 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix API test failures and improve test reliability - Fix ApiRateLimiterTest by removing mock users method and using fixtures - Fix UsageControllerTest by removing mock users method and using fixtures - Fix BaseControllerTest by using different users for multiple API keys - Use unique display_key values with SecureRandom to avoid conflicts - Fix double render issue in UsageController by returning after authorize_scope\! - Specify controller name in routes for usage resource - Remove trailing whitespace and empty lines per Rubocop All tests now pass and linting is clean. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Add API transactions controller warning to brakeman ignore The account_id parameter in the API transactions controller is properly validated on line 79: family.accounts.find(transaction_params[:account_id]) This ensures users can only create transactions in accounts belonging to their family, making this a false positive. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Signed-off-by: Josh Pigford <josh@joshpigford.com> Co-authored-by: Claude <noreply@anthropic.com>
7.3 KiB
7.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Common Development Commands
Development Server
bin/dev- Start development server (Rails, Sidekiq, Tailwind CSS watcher)bin/rails server- Start Rails server onlybin/rails console- Open Rails console
Testing
bin/rails test- Run all testsbin/rails test:db- Run tests with database resetbin/rails test:system- Run system tests onlybin/rails test test/models/account_test.rb- Run specific test filebin/rails test test/models/account_test.rb:42- Run specific test at line
Linting & Formatting
bin/rubocop- Run Ruby linternpm run lint- Check JavaScript/TypeScript codenpm run lint:fix- Fix JavaScript/TypeScript issuesnpm run format- Format JavaScript/TypeScript codebin/brakeman- Run security analysis
Database
bin/rails db:prepare- Create and migrate databasebin/rails db:migrate- Run pending migrationsbin/rails db:rollback- Rollback last migrationbin/rails db:seed- Load seed data
Setup
bin/setup- Initial project setup (installs dependencies, prepares database)
General Development Rules
Authentication Context
- Use
Current.userfor the current user. Do NOT usecurrent_user. - Use
Current.familyfor the current family. Do NOT usecurrent_family.
Development Guidelines
- Prior to generating any code, carefully read the project conventions and guidelines
- Ignore i18n methods and files. Hardcode strings in English for now to optimize speed of development
- Do not run
rails serverin your responses - Do not run
touch tmp/restart.txt - Do not run
rails credentials - Do not automatically run migrations
High-Level Architecture
Application Modes
The Maybe app runs in two distinct modes:
- Managed: The Maybe team operates and manages servers for users (Rails.application.config.app_mode = "managed")
- Self Hosted: Users host the Maybe app on their own infrastructure, typically through Docker Compose (Rails.application.config.app_mode = "self_hosted")
Core Domain Model
The application is built around financial data management with these key relationships:
- User → has many Accounts → has many Transactions
- Account types: checking, savings, credit cards, investments, crypto, loans, properties
- Transaction → belongs to Category, can have Tags and Rules
- Investment accounts → have Holdings → track Securities via Trades
API Architecture
The application provides both internal and external APIs:
- Internal API: Controllers serve JSON via Turbo for SPA-like interactions
- External API:
/api/v1/namespace with Doorkeeper OAuth and API key authentication - API responses use Jbuilder templates for JSON rendering
- Rate limiting via Rack Attack with configurable limits per API key
Sync & Import System
Two primary data ingestion methods:
- Plaid Integration: Real-time bank account syncing
PlaidItemmanages connectionsSynctracks sync operations- Background jobs handle data updates
- CSV Import: Manual data import with mapping
Importmanages import sessions- Supports transaction and balance imports
- Custom field mapping with transformation rules
Background Processing
Sidekiq handles asynchronous tasks:
- Account syncing (
SyncAccountsJob) - Import processing (
ImportDataJob) - AI chat responses (
CreateChatResponseJob) - Scheduled maintenance via sidekiq-cron
Frontend Architecture
- Hotwire Stack: Turbo + Stimulus for reactive UI without heavy JavaScript
- ViewComponents: Reusable UI components in
app/components/ - Stimulus Controllers: Handle interactivity, organized alongside components
- Charts: D3.js for financial visualizations (time series, donut, sankey)
- Styling: Tailwind CSS v4.x with custom design system
- Design system defined in
app/assets/tailwind/maybe-design-system.css - Always use functional tokens (e.g.,
text-primarynottext-white) - Prefer semantic HTML elements over JS components
- Use
iconhelper for icons, neverlucide_icondirectly
- Design system defined in
Multi-Currency Support
- All monetary values stored in base currency (user's primary currency)
- Exchange rates fetched from Synth API
Moneyobjects handle currency conversion and formatting- Historical exchange rates for accurate reporting
Security & Authentication
- Session-based auth for web users
- API authentication via:
- OAuth2 (Doorkeeper) for third-party apps
- API keys with JWT tokens for direct API access
- Scoped permissions system for API access
- Strong parameters and CSRF protection throughout
Key Service Objects & Patterns
- Query Objects: Complex database queries isolated in
app/queries/ - Service Objects: Business logic in
app/services/ - Form Objects: Complex forms with validation
- Concerns: Shared functionality across models/controllers
- Jobs: Background processing logic
Testing Philosophy
- Comprehensive test coverage using Rails' built-in Minitest
- Fixtures for test data (avoid FactoryBot)
- Keep fixtures minimal (2-3 per model for base cases)
- VCR for external API testing
- System tests for critical user flows (use sparingly)
- Test helpers in
test/support/for common scenarios - Only test critical code paths that significantly increase confidence
- Write tests as you go, when required
Performance Considerations
- Database queries optimized with proper indexes
- N+1 queries prevented via includes/joins
- Background jobs for heavy operations
- Caching strategies for expensive calculations
- Turbo Frames for partial page updates
Development Workflow
- Feature branches merged to
main - Docker support for consistent environments
- Environment variables via
.envfiles - Lookbook for component development (
/lookbook) - Letter Opener for email preview in development
Project Conventions
Convention 1: Minimize Dependencies
- Push Rails to its limits before adding new dependencies
- When adding dependencies, favor old and reliable over new and flashy
- Strong technical or business reason required for new dependencies
Convention 2: POROs and Concerns over Service Objects
- "Skinny controller, fat models" convention
- Everything in
app/models/folder, avoid separate folders likeapp/services/ - Use Rails concerns for better organization (can be one-off concerns)
- Models should answer questions about themselves (e.g.,
account.balance_series)
Convention 3: Leverage Hotwire and Server-Side Solutions
- Native HTML preferred over JS components (e.g.,
<dialog>,<details>) - Use Turbo frames to break up pages
- Leverage query params for state over local storage
- Format values server-side, pass to Stimulus for display only
- Client-side code only where it truly shines (e.g., bulk selections)
Convention 4: Optimize for Simplicity and Clarity
- Prioritize good OOP domain design over performance
- Only focus on performance in critical/global areas
- Be mindful of N+1 queries and large data payloads
Convention 5: ActiveRecord for Complex Validations, DB for Simple Ones
- Enforce null checks, unique indexes in the DB
- ActiveRecord validations for convenience in forms
- Complex validations and business logic in ActiveRecord