RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Diff/we-promise-sure-cursor-rules-cursor-rules ↔ we-promise-sure-claude

Comparison

A · Cursor rules · we-promise/sureB · CLAUDE.md · we-promise/sure
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections00470%
Commands0060%
Section tags00150%

What each file covers

Sections

0 shared · 0 only in A · 47 only in B
  • + CLAUDE.md
  • + Common Development Commands
  • + Development Server
  • + Testing
  • + Linting & Formatting
  • + Database
  • + Setup
  • + Pre-Pull Request CI Workflow
  • + General Development Rules
  • + Authentication Context
  • + Development Guidelines
  • + High-Level Architecture
  • + Application Modes
  • + Core Domain Model
  • + API Architecture
  • + Sync & Import System
  • + Provider Integrations: Pending Transactions and FX (SimpleFIN/Plaid)
  • + Background Processing
  • + Debug Logging for Provider Syncs
  • + Frontend Architecture
  • + Internationalization (i18n) Guidelines
  • + Multi-Currency Support
  • + Security & Authentication
  • + Testing Philosophy
  • + Performance Considerations
  • + Development Workflow
  • + Project Conventions
  • + Convention 1: Minimize Dependencies
  • + Convention 2: Skinny Controllers, Fat Models
  • + Convention 3: Hotwire-First Frontend
  • + Convention 4: Optimize for Simplicity
  • + Convention 5: Database vs ActiveRecord Validations
  • + TailwindCSS Design System
  • + Design System Rules
  • + Component Architecture
  • + ViewComponent vs Partials Decision Making
  • + Stimulus Controller Guidelines
  • + General Testing Rules
  • + Test Quality Guidelines
  • + Testing Examples
  • + GOOD - Testing critical domain business logic
  • + BAD - Testing ActiveRecord functionality
  • + Stubs and Mocks
  • + API Development Guidelines
  • + OpenAPI Documentation (MANDATORY)
  • + spec/requests/api/v1/widgets_spec.rb
  • + Post-commit API consistency (issue #944)

Commands

0 shared · 0 only in A · 6 only in B
  • + npm run lint
  • + npm run lint:fix
  • + npm run format
  • + bundle exec erb_lint ./app/**/*.erb -a
  • + rails server
  • + rails credentials

Section tags

0 shared · 0 only in A · 15 only in B
  • + setup
  • + test
  • + lint-format
  • + code-style
  • + testing-strategy
  • + git-pr
  • + security
  • + dependencies
  • + database
  • + api
  • + ui
  • + performance
  • + do-not
  • + agent-behaviour
  • + docs

Line diff

+384 added−46 removed9 unchanged2.3% identical
we-promise/sure · .cursor/rules/cursor_rules.mdc
@@ −1 @@
1---
2description: Guidelines for creating and maintaining Cursor rules to ensure consistency and effectiveness.
3globs: .cursor/rules/*.mdc
4alwaysApply: true
5---
6 
7- **Required Rule Structure:**
8 ```markdown
9 ---
10 description: Clear, one-line description of what the rule enforces
11 globs: path/to/files/*.ext, other/path/**/*
12 alwaysApply: boolean
13 ---
14 
15 - **Main Points in Bold**
16 - Sub-points with details
17 - Examples and explanations
18 ```
19 
20- **File References:**
21 - Use `[filename](mdc:path/to/file)` ([filename](mdc:filename)) to reference files
22 - Example: [prisma.mdc](mdc:.cursor/rules/prisma.mdc) for rule references
23 - Example: [schema.prisma](mdc:prisma/schema.prisma) for code references
24 
25- **Code Examples:**
26 - Use language-specific code blocks
27 ```typescript
28 // ✅ DO: Show good examples
29 const goodExample = true;
30
31 // ❌ DON'T: Show anti-patterns
32 const badExample = false;
33 ```
34 
35- **Rule Content Guidelines:**
36 - Start with high-level overview
37 - Include specific, actionable requirements
38 - Show examples of correct implementation
39 - Reference existing code when possible
40 - Keep rules DRY by referencing other rules
41 
42- **Rule Maintenance:**
43 - Update rules when new patterns emerge
44 - Add examples from actual codebase
45 - Remove outdated patterns
46 - Cross-reference related rules
47 
48- **Best Practices:**
49 - Use bullet points for clarity
50 - Keep descriptions concise
51 - Include both DO and DON'T examples
52 - Reference actual code over theoretical examples
53 - Use consistent formatting across rules
54 
 
 
 
 
 
 
55 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
we-promise/sure · CLAUDE.md
@@ +1 @@
1# CLAUDE.md
 
 
 
 
2 
3This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
 
 
 
 
 
 
4 
5## Common Development Commands
 
 
 
6 
7### Development Server
8- `bin/dev` - Start development server (Rails, Sidekiq, Tailwind CSS watcher)
9- `bin/rails server` - Start Rails server only
10- `bin/rails console` - Open Rails console
11 
12### Testing
13- `bin/rails test` - Run all tests
14- `bin/rails test:db` - Run tests with database reset
15- `DISABLE_PARALLELIZATION=true bin/rails test:system` - Run system tests only (use sparingly - they take longer)
16- `bin/rails test test/models/account_test.rb` - Run specific test file
17- `bin/rails test test/models/account_test.rb:42` - Run specific test at line
 
 
 
18 
19#### System Tests in the Dev Container
20When running inside the Dev Container, the `SELENIUM_REMOTE_URL` environment variable is automatically set to the bundled `selenium/standalone-chromium` service. System tests will connect to that remote browser — no local Chrome installation is required.
 
 
 
 
21 
22```bash
23DISABLE_PARALLELIZATION=true bin/rails test:system
24```
 
 
25 
26To watch the browser live, open `http://localhost:7900` or `http://localhost:4444` in your host browser (password: `secret`).
 
 
 
 
 
27 
28### Linting & Formatting
29- `bin/rubocop` - Run Ruby linter
30- `npm run lint` - Check JavaScript/TypeScript code
31- `npm run lint:fix` - Fix JavaScript/TypeScript issues
32- `npm run format` - Format JavaScript/TypeScript code
33- `bin/brakeman` - Run security analysis
34 
35### Database
36- `bin/rails db:prepare` - Create and migrate database
37- `bin/rails db:migrate` - Run pending migrations
38- `bin/rails db:rollback` - Rollback last migration
39- `bin/rails db:seed` - Load seed data
40 
41### Setup
42- `bin/setup` - Initial project setup (installs dependencies, prepares database)
43 
44## Pre-Pull Request CI Workflow
45 
46ALWAYS run these commands before opening a pull request:
47 
481. **Tests** (Required):
49 - `bin/rails test` - Run all tests (always required)
50 - `DISABLE_PARALLELIZATION=true bin/rails test:system` - Run system tests (only when applicable, they take longer)
51 
522. **Linting** (Required):
53 - `bin/rubocop -f github -a` - Ruby linting with auto-correct
54 - `bundle exec erb_lint ./app/**/*.erb -a` - ERB linting with auto-correct
55 
563. **Security** (Required):
57 - `bin/brakeman --no-pager` - Security analysis
58 
59Only proceed with pull request creation if ALL checks pass.
60 
61## General Development Rules
62 
63### Authentication Context
64- Use `Current.user` for the current user. Do NOT use `current_user`.
65- Use `Current.family` for the current family. Do NOT use `current_family`.
66 
67### Development Guidelines
68- Carefully read project conventions and guidelines before generating any code.
69- Do not run `rails server` in your responses
70- Do not run `touch tmp/restart.txt`
71- Do not run `rails credentials`
72- Do not automatically run migrations
73 
74## High-Level Architecture
75 
76### Application Modes
77The codebase runs in two distinct modes:
78- **Managed**: A team operates and manages servers for users (Rails.application.config.app_mode = "managed")
79- **Self Hosted**: Users host the codebase on their own infrastructure, typically through Docker Compose (Rails.application.config.app_mode = "self_hosted")
80 
81### Core Domain Model
82The application is built around financial data management with these key relationships:
83- **User** → has many **Accounts** → has many **Transactions**
84- **Account** types: checking, savings, credit cards, investments, crypto, loans, properties
85- **Transaction** → belongs to **Category**, can have **Tags** and **Rules**
86- **Investment accounts** → have **Holdings** → track **Securities** via **Trades**
87 
88### API Architecture
89The application provides both internal and external APIs:
90- Internal API: Controllers serve JSON via Turbo for SPA-like interactions
91- External API: `/api/v1/` namespace with Doorkeeper OAuth and API key authentication
92- API responses use Jbuilder templates for JSON rendering
93- Rate limiting via Rack Attack with configurable limits per API key
94- **OpenAPI Documentation**: All API endpoints MUST have corresponding OpenAPI specs in `spec/requests/api/` using rswag. See `docs/api/openapi.yaml` for the generated documentation.
95 
96### Sync & Import System
97Two primary data ingestion methods:
981. **Plaid Integration**: Real-time bank account syncing
99 - `PlaidItem` manages connections
100 - `Sync` tracks sync operations
101 - Background jobs handle data updates
1022. **CSV Import**: Manual data import with mapping
103 - `Import` manages import sessions
104 - Supports transaction and balance imports
105 - Custom field mapping with transformation rules
106 
107### Provider Integrations: Pending Transactions and FX (SimpleFIN/Plaid)
108 
109- Detection
110 - SimpleFIN: pending via `pending: true` or `posted` blank/0 + `transacted_at`.
111 - Plaid: pending via Plaid `pending: true` (stored at `extra["plaid"]["pending"]` for bank/credit transactions imported via `PlaidEntry::Processor`).
112- Storage: provider data on `Transaction#extra` (e.g., `extra["simplefin"]["pending"]`; FX uses `fx_from`, `fx_date`).
113- UI: "Pending" badge when `transaction.pending?` is true; no badge if provider omits pendings.
114- Configuration (default-on for pending)
115 - SimpleFIN: `config/initializers/simplefin.rb` via `Rails.configuration.x.simplefin.*`.
116 - Plaid: `config/initializers/plaid_config.rb` via `Rails.configuration.x.plaid.*`.
117 - Pending transactions are fetched by default and handled via reconciliation/filtering.
118 - Set `SIMPLEFIN_INCLUDE_PENDING=0` to disable pending fetching for SimpleFIN.
119 - Set `PLAID_INCLUDE_PENDING=0` to disable pending fetching for Plaid.
120 - Set `SIMPLEFIN_DEBUG_RAW=1` to enable raw payload debug logging.
121 - Set `UP_DEBUG_RAW=1` to enable raw Up payload debug logging. DEV-ONLY: the dump contains PII and is gated to local environments, so it never logs in managed/production.
122 
123Provider support notes:
124- SimpleFIN: supports pending + FX metadata (stored under `extra["simplefin"]`).
125- Plaid: supports pending when the upstream Plaid payload includes `pending: true` (stored under `extra["plaid"]`).
126- Plaid investments: investment transactions currently do not store pending metadata.
127- Lunchflow: does not currently store pending metadata.
128 
129### Background Processing
130Sidekiq handles asynchronous tasks:
131- Account syncing (`SyncJob`)
132- Import processing (`ImportJob`)
133- AI chat responses (`AssistantResponseJob`)
134- Scheduled maintenance via sidekiq-cron
135 
136### Debug Logging for Provider Syncs
137- Prefer `DebugLogEntry.capture(...)` over `Rails.logger.*` for provider sync/import failures, partial responses, and other support-relevant diagnostics.
138- Record support-relevant incidents in the super-admin `/settings/debug` UI rather than leaving them only in raw application logs.
139- Include `category`, `level`, `message`, `source`, `provider_key`, and structured `metadata`.
140- Attach `family` and `account_provider` whenever possible so support can filter to the affected provider connection.
141 
142### Frontend Architecture
143- **Hotwire Stack**: Turbo + Stimulus for reactive UI without heavy JavaScript
144- **ViewComponents**: Reusable UI components in `app/components/`
145- **Stimulus Controllers**: Handle interactivity, organized alongside components
146- **Charts**: D3.js for financial visualizations (time series, donut, sankey)
147- **Styling**: Tailwind CSS v4.x with custom design system
148 - Design system defined in `app/assets/tailwind/sure-design-system.css`
149 - Always use functional tokens (e.g., `text-primary` not `text-white`)
150 - Prefer semantic HTML elements over JS components
151 - Use `icon` helper for icons, never `lucide_icon` directly
152- **i18n**: All user-facing strings must use localization (i18n). Update locale files for each new or changed element.
153 
154### Internationalization (i18n) Guidelines
155- **Key Organization**: Use hierarchical keys by feature: `accounts.index.title`, `transactions.form.amount_label`
156- **Translation Helper**: Always use `t()` helper for user-facing strings
157- **Interpolation**: Use for dynamic content: `t("users.greeting", name: user.name)`
158- **Pluralization**: Use Rails pluralization: `t("transactions.count", count: @transactions.count)`
159- **Locale Files**: Update `config/locales/en.yml` for new strings
160- **Missing Translations**: Configure to raise errors in development for missing keys
161 
162### Multi-Currency Support
163- All monetary values stored in base currency (user's primary currency)
164- `Money` objects handle currency conversion and formatting
165- Historical exchange rates for accurate reporting
166 
167### Security & Authentication
168- Session-based auth for web users
169- API authentication via:
170 - OAuth2 (Doorkeeper) for third-party apps
171 - API keys with JWT tokens for direct API access
172- Scoped permissions system for API access
173- Strong parameters and CSRF protection throughout
174 
175### Testing Philosophy
176- Comprehensive test coverage using Rails' built-in Minitest
177- Fixtures for test data (avoid FactoryBot)
178- Keep fixtures minimal (2-3 per model for base cases)
179- VCR for external API testing
180- System tests for critical user flows (use sparingly)
181- Test helpers in `test/support/` for common scenarios
182- Only test critical code paths that significantly increase confidence
183- Write tests as you go, when required
184- **API Endpoints require OpenAPI specs** in `spec/requests/api/` for documentation purposes ONLY, not test (uses RSpec + rswag)
185 
186### Performance Considerations
187- Database queries optimized with proper indexes
188- N+1 queries prevented via includes/joins
189- Background jobs for heavy operations
190- Caching strategies for expensive calculations
191- Turbo Frames for partial page updates
192 
193### Development Workflow
194- Feature branches merged to `main`
195- Docker support for consistent environments
196- Environment variables via `.env` files
197- Lookbook for component development (`/lookbook`)
198- Letter Opener for email preview in development
199 
200## Project Conventions
201 
202### Convention 1: Minimize Dependencies
203- Push Rails to its limits before adding new dependencies
204- Strong technical/business reason required for new dependencies
205- Favor old and reliable over new and flashy
206 
207### Convention 2: Skinny Controllers, Fat Models
208- Business logic in `app/models/` folder, avoid `app/services/`
209- Use Rails concerns and POROs for organization
210- Models should answer questions about themselves: `account.balance_series` not `AccountSeries.new(account).call`
211 
212### Convention 3: Hotwire-First Frontend
213- **Native HTML preferred over JS components**
214 - Use `<dialog>` for modals, `<details><summary>` for disclosures
215- **Leverage Turbo frames** for page sections over client-side solutions
216- **Query params for state** over localStorage/sessions
217- **Server-side formatting** for currencies, numbers, dates
218- **Always use `icon` helper** in `application_helper.rb`, NEVER `lucide_icon` directly
219 
220### Convention 4: Optimize for Simplicity
221- Prioritize good OOP domain design over performance
222- Focus performance only on critical/global areas (avoid N+1 queries, mindful of global layouts)
223 
224### Convention 5: Database vs ActiveRecord Validations
225- Simple validations (null checks, unique indexes) in DB
226- ActiveRecord validations for convenience in forms (prefer client-side when possible)
227- Complex validations and business logic in ActiveRecord
228 
229## TailwindCSS Design System
230 
231### Design System Rules
232- **Always reference `app/assets/tailwind/sure-design-system.css`** for primitives and tokens
233- **Use functional tokens** defined in design system:
234 - `text-primary` instead of `text-white`
235 - `bg-container` instead of `bg-white`
236 - `border border-primary` instead of `border border-gray-200`
237- **NEVER create new styles** in design system files without permission
238- **Always generate semantic HTML**
239 
240## Component Architecture
241 
242### ViewComponent vs Partials Decision Making
243 
244**Use ViewComponents when:**
245- Element has complex logic or styling patterns
246- Element will be reused across multiple views/contexts
247- Element needs structured styling with variants/sizes
248- Element requires interactive behavior or Stimulus controllers
249- Element has configurable slots or complex APIs
250- Element needs accessibility features or ARIA support
251 
252**Use Partials when:**
253- Element is primarily static HTML with minimal logic
254- Element is used in only one or few specific contexts
255- Element is simple template content
256- Element doesn't need variants, sizes, or complex configuration
257- Element is more about content organization than reusable functionality
258 
259**Component Guidelines:**
260- Prefer components over partials when available
261- Keep domain logic OUT of view templates
262- Logic belongs in component files, not template files
263 
264### Stimulus Controller Guidelines
265 
266**Declarative Actions (Required):**
267```erb
268<!-- GOOD: Declarative - HTML declares what happens -->
269<div data-controller="toggle">
270 <button data-action="click->toggle#toggle" data-toggle-target="button">
271 <%= t("components.transaction_details.show_details") %>
272 </button>
273 <div data-toggle-target="content" class="hidden">
274 <p><%= t("components.transaction_details.amount_label") %>: <%= @transaction.amount %></p>
275 <p><%= t("components.transaction_details.date_label") %>: <%= @transaction.date %></p>
276 <p><%= t("components.transaction_details.category_label") %>: <%= @transaction.category.name %></p>
277 </div>
278</div>
279```
280 
281**Example locale file structure (config/locales/en.yml):**
282```yaml
283en:
284 components:
285 transaction_details:
286 show_details: "Show Details"
287 hide_details: "Hide Details"
288 amount_label: "Amount"
289 date_label: "Date"
290 category_label: "Category"
291```
292 
293**i18n Best Practices:**
294- Organize keys by feature/component: `components.transaction_details.show_details`
295- Use descriptive key names that indicate purpose: `show_details` not `button`
296- Group related translations together in the same namespace
297- Use interpolation for dynamic content: `t("users.welcome", name: user.name)`
298- Always update locale files when adding new user-facing strings
299 
300**Controller Best Practices:**
301- Keep controllers lightweight and simple (< 7 targets)
302- Use private methods and expose clear public API
303- Single responsibility or highly related responsibilities
304- Component controllers stay in component directory, global controllers in `app/javascript/controllers/`
305- Pass data via `data-*-value` attributes, not inline JavaScript
306 
307## Testing Philosophy
308 
309### General Testing Rules
310- **ALWAYS use Minitest + fixtures** (NEVER RSpec or factories)
311- Keep fixtures minimal (2-3 per model for base cases)
312- Create edge cases on-the-fly within test context
313- Use Rails helpers for large fixture creation needs
314 
315### Test Quality Guidelines
316- **Write minimal, effective tests** - system tests sparingly
317- **Only test critical and important code paths**
318- **Test boundaries correctly:**
319 - Commands: test they were called with correct params
320 - Queries: test output
321 - Don't test implementation details of other classes
322 
323### Testing Examples
324 
325```ruby
326# GOOD - Testing critical domain business logic
327test "syncs balances" do
328 Holding::Syncer.any_instance.expects(:sync_holdings).returns([]).once
329 assert_difference "@account.balances.count", 2 do
330 Balance::Syncer.new(@account, strategy: :forward).sync_balances
331 end
332end
333 
334# BAD - Testing ActiveRecord functionality
335test "saves balance" do
336 balance_record = Balance.new(balance: 100, currency: "USD")
337 assert balance_record.save
338end
339```
340 
341### Stubs and Mocks
342- Use `mocha` gem
343- Prefer `OpenStruct` for mock instances
344- Only mock what's necessary
345 
346## API Development Guidelines
347 
348### OpenAPI Documentation (MANDATORY)
349When adding or modifying API endpoints in `app/controllers/api/v1/`, you **MUST** create or update corresponding OpenAPI request specs:
350 
3511. **Location**: `spec/requests/api/v1/{resource}_spec.rb`
3522. **Framework**: RSpec with rswag for OpenAPI generation
3533. **Schemas**: Define reusable schemas in `spec/swagger_helper.rb`
3544. **Generated Docs**: `docs/api/openapi.yaml`
355 
356**Example structure for a new API endpoint:**
357```ruby
358# spec/requests/api/v1/widgets_spec.rb
359require 'swagger_helper'
360 
361RSpec.describe 'API V1 Widgets', type: :request do
362 path '/api/v1/widgets' do
363 get 'List widgets' do
364 tags 'Widgets'
365 security [ { apiKeyAuth: [] } ]
366 produces 'application/json'
367
368 response '200', 'widgets listed' do
369 schema '$ref' => '#/components/schemas/WidgetCollection'
370 run_test!
371 end
372 end
373 end
374end
375```
376 
377**Regenerate OpenAPI docs after changes:**
378```bash
379RAILS_ENV=test bundle exec rake rswag:specs:swaggerize
380```
381 
382### Post-commit API consistency (issue #944)
383After every API endpoint commit, ensure:
384 
3851. **Minitest behavioral coverage** — Add or update tests in `test/controllers/api/v1/{resource}_controller_test.rb`. Use API key and `api_headers` (X-Api-Key). Cover index/show, CRUD where relevant, 401/403/422/404. Do not rely on rswag for behavioral assertions.
386 
3872. **rswag docs-only** — Do not add `expect(...)` or `assert_*` in `spec/requests/api/v1/`. Use `run_test!` only so specs document request/response and regenerate `docs/api/openapi.yaml`.
388 
3893. **Same API key auth in rswag** — Every request spec in `spec/requests/api/v1/` must use the same API key pattern (`ApiKey.generate_secure_key`, `ApiKey.create!(...)`, `let(:'X-Api-Key') { api_key.plain_key }`). Do not use Doorkeeper/OAuth in those specs so generated docs stay consistent.
390 
391Full checklist and pattern: [.cursor/rules/api-endpoint-consistency.mdc](.cursor/rules/api-endpoint-consistency.mdc).
392 
393To verify the implementation: `ruby test/support/verify_api_endpoint_consistency.rb`. To scan the current APIs for violations: `ruby test/support/verify_api_endpoint_consistency.rb --compliance`.
@@ −1 +1 @@
1−---
2−description: Guidelines for creating and maintaining Cursor rules to ensure consistency and effectiveness.
3−globs: .cursor/rules/*.mdc
4−alwaysApply: true
5−---
1+# CLAUDE.md
62  
7−- **Required Rule Structure:**
8− ```markdown
9− ---
10− description: Clear, one-line description of what the rule enforces
11− globs: path/to/files/*.ext, other/path/**/*
12− alwaysApply: boolean
13− ---
3+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
144  
15− - **Main Points in Bold**
16− - Sub-points with details
17− - Examples and explanations
18− ```
5+## Common Development Commands
196  
20−- **File References:**
21− - Use `[filename](mdc:path/to/file)` ([filename](mdc:filename)) to reference files
22− - Example: [prisma.mdc](mdc:.cursor/rules/prisma.mdc) for rule references
23− - Example: [schema.prisma](mdc:prisma/schema.prisma) for code references
7+### Development Server
8+- `bin/dev` - Start development server (Rails, Sidekiq, Tailwind CSS watcher)
9+- `bin/rails server` - Start Rails server only
10+- `bin/rails console` - Open Rails console
2411  
25−- **Code Examples:**
26− - Use language-specific code blocks
27− ```typescript
28− // ✅ DO: Show good examples
29− const goodExample = true;
30−
31− // ❌ DON'T: Show anti-patterns
32− const badExample = false;
33− ```
12+### Testing
13+- `bin/rails test` - Run all tests
14+- `bin/rails test:db` - Run tests with database reset
15+- `DISABLE_PARALLELIZATION=true bin/rails test:system` - Run system tests only (use sparingly - they take longer)
16+- `bin/rails test test/models/account_test.rb` - Run specific test file
17+- `bin/rails test test/models/account_test.rb:42` - Run specific test at line
3418  
35−- **Rule Content Guidelines:**
36− - Start with high-level overview
37− - Include specific, actionable requirements
38− - Show examples of correct implementation
39− - Reference existing code when possible
40− - Keep rules DRY by referencing other rules
19+#### System Tests in the Dev Container
20+When running inside the Dev Container, the `SELENIUM_REMOTE_URL` environment variable is automatically set to the bundled `selenium/standalone-chromium` service. System tests will connect to that remote browser — no local Chrome installation is required.
4121  
42−- **Rule Maintenance:**
43− - Update rules when new patterns emerge
44− - Add examples from actual codebase
45− - Remove outdated patterns
46− - Cross-reference related rules
22+```bash
23+DISABLE_PARALLELIZATION=true bin/rails test:system
24+```
4725  
48−- **Best Practices:**
49− - Use bullet points for clarity
50− - Keep descriptions concise
51− - Include both DO and DON'T examples
52− - Reference actual code over theoretical examples
53− - Use consistent formatting across rules
26+To watch the browser live, open `http://localhost:7900` or `http://localhost:4444` in your host browser (password: `secret`).
5427  
28+### Linting & Formatting
29+- `bin/rubocop` - Run Ruby linter
30+- `npm run lint` - Check JavaScript/TypeScript code
31+- `npm run lint:fix` - Fix JavaScript/TypeScript issues
32+- `npm run format` - Format JavaScript/TypeScript code
33+- `bin/brakeman` - Run security analysis
5534  
35+### Database
36+- `bin/rails db:prepare` - Create and migrate database
37+- `bin/rails db:migrate` - Run pending migrations
38+- `bin/rails db:rollback` - Rollback last migration
39+- `bin/rails db:seed` - Load seed data
40+ 
41+### Setup
42+- `bin/setup` - Initial project setup (installs dependencies, prepares database)
43+ 
44+## Pre-Pull Request CI Workflow
45+ 
46+ALWAYS run these commands before opening a pull request:
47+ 
48+1. **Tests** (Required):
49+ - `bin/rails test` - Run all tests (always required)
50+ - `DISABLE_PARALLELIZATION=true bin/rails test:system` - Run system tests (only when applicable, they take longer)
51+ 
52+2. **Linting** (Required):
53+ - `bin/rubocop -f github -a` - Ruby linting with auto-correct
54+ - `bundle exec erb_lint ./app/**/*.erb -a` - ERB linting with auto-correct
55+ 
56+3. **Security** (Required):
57+ - `bin/brakeman --no-pager` - Security analysis
58+ 
59+Only proceed with pull request creation if ALL checks pass.
60+ 
61+## General Development Rules
62+ 
63+### Authentication Context
64+- Use `Current.user` for the current user. Do NOT use `current_user`.
65+- Use `Current.family` for the current family. Do NOT use `current_family`.
66+ 
67+### Development Guidelines
68+- Carefully read project conventions and guidelines before generating any code.
69+- Do not run `rails server` in your responses
70+- Do not run `touch tmp/restart.txt`
71+- Do not run `rails credentials`
72+- Do not automatically run migrations
73+ 
74+## High-Level Architecture
75+ 
76+### Application Modes
77+The codebase runs in two distinct modes:
78+- **Managed**: A team operates and manages servers for users (Rails.application.config.app_mode = "managed")
79+- **Self Hosted**: Users host the codebase on their own infrastructure, typically through Docker Compose (Rails.application.config.app_mode = "self_hosted")
80+ 
81+### Core Domain Model
82+The application is built around financial data management with these key relationships:
83+- **User** → has many **Accounts** → has many **Transactions**
84+- **Account** types: checking, savings, credit cards, investments, crypto, loans, properties
85+- **Transaction** → belongs to **Category**, can have **Tags** and **Rules**
86+- **Investment accounts** → have **Holdings** → track **Securities** via **Trades**
87+ 
88+### API Architecture
89+The application provides both internal and external APIs:
90+- Internal API: Controllers serve JSON via Turbo for SPA-like interactions
91+- External API: `/api/v1/` namespace with Doorkeeper OAuth and API key authentication
92+- API responses use Jbuilder templates for JSON rendering
93+- Rate limiting via Rack Attack with configurable limits per API key
94+- **OpenAPI Documentation**: All API endpoints MUST have corresponding OpenAPI specs in `spec/requests/api/` using rswag. See `docs/api/openapi.yaml` for the generated documentation.
95+ 
96+### Sync & Import System
97+Two primary data ingestion methods:
98+1. **Plaid Integration**: Real-time bank account syncing
99+ - `PlaidItem` manages connections
100+ - `Sync` tracks sync operations
101+ - Background jobs handle data updates
102+2. **CSV Import**: Manual data import with mapping
103+ - `Import` manages import sessions
104+ - Supports transaction and balance imports
105+ - Custom field mapping with transformation rules
106+ 
107+### Provider Integrations: Pending Transactions and FX (SimpleFIN/Plaid)
108+ 
109+- Detection
110+ - SimpleFIN: pending via `pending: true` or `posted` blank/0 + `transacted_at`.
111+ - Plaid: pending via Plaid `pending: true` (stored at `extra["plaid"]["pending"]` for bank/credit transactions imported via `PlaidEntry::Processor`).
112+- Storage: provider data on `Transaction#extra` (e.g., `extra["simplefin"]["pending"]`; FX uses `fx_from`, `fx_date`).
113+- UI: "Pending" badge when `transaction.pending?` is true; no badge if provider omits pendings.
114+- Configuration (default-on for pending)
115+ - SimpleFIN: `config/initializers/simplefin.rb` via `Rails.configuration.x.simplefin.*`.
116+ - Plaid: `config/initializers/plaid_config.rb` via `Rails.configuration.x.plaid.*`.
117+ - Pending transactions are fetched by default and handled via reconciliation/filtering.
118+ - Set `SIMPLEFIN_INCLUDE_PENDING=0` to disable pending fetching for SimpleFIN.
119+ - Set `PLAID_INCLUDE_PENDING=0` to disable pending fetching for Plaid.
120+ - Set `SIMPLEFIN_DEBUG_RAW=1` to enable raw payload debug logging.
121+ - Set `UP_DEBUG_RAW=1` to enable raw Up payload debug logging. DEV-ONLY: the dump contains PII and is gated to local environments, so it never logs in managed/production.
122+ 
123+Provider support notes:
124+- SimpleFIN: supports pending + FX metadata (stored under `extra["simplefin"]`).
125+- Plaid: supports pending when the upstream Plaid payload includes `pending: true` (stored under `extra["plaid"]`).
126+- Plaid investments: investment transactions currently do not store pending metadata.
127+- Lunchflow: does not currently store pending metadata.
128+ 
129+### Background Processing
130+Sidekiq handles asynchronous tasks:
131+- Account syncing (`SyncJob`)
132+- Import processing (`ImportJob`)
133+- AI chat responses (`AssistantResponseJob`)
134+- Scheduled maintenance via sidekiq-cron
135+ 
136+### Debug Logging for Provider Syncs
137+- Prefer `DebugLogEntry.capture(...)` over `Rails.logger.*` for provider sync/import failures, partial responses, and other support-relevant diagnostics.
138+- Record support-relevant incidents in the super-admin `/settings/debug` UI rather than leaving them only in raw application logs.
139+- Include `category`, `level`, `message`, `source`, `provider_key`, and structured `metadata`.
140+- Attach `family` and `account_provider` whenever possible so support can filter to the affected provider connection.
141+ 
142+### Frontend Architecture
143+- **Hotwire Stack**: Turbo + Stimulus for reactive UI without heavy JavaScript
144+- **ViewComponents**: Reusable UI components in `app/components/`
145+- **Stimulus Controllers**: Handle interactivity, organized alongside components
146+- **Charts**: D3.js for financial visualizations (time series, donut, sankey)
147+- **Styling**: Tailwind CSS v4.x with custom design system
148+ - Design system defined in `app/assets/tailwind/sure-design-system.css`
149+ - Always use functional tokens (e.g., `text-primary` not `text-white`)
150+ - Prefer semantic HTML elements over JS components
151+ - Use `icon` helper for icons, never `lucide_icon` directly
152+- **i18n**: All user-facing strings must use localization (i18n). Update locale files for each new or changed element.
153+ 
154+### Internationalization (i18n) Guidelines
155+- **Key Organization**: Use hierarchical keys by feature: `accounts.index.title`, `transactions.form.amount_label`
156+- **Translation Helper**: Always use `t()` helper for user-facing strings
157+- **Interpolation**: Use for dynamic content: `t("users.greeting", name: user.name)`
158+- **Pluralization**: Use Rails pluralization: `t("transactions.count", count: @transactions.count)`
159+- **Locale Files**: Update `config/locales/en.yml` for new strings
160+- **Missing Translations**: Configure to raise errors in development for missing keys
161+ 
162+### Multi-Currency Support
163+- All monetary values stored in base currency (user's primary currency)
164+- `Money` objects handle currency conversion and formatting
165+- Historical exchange rates for accurate reporting
166+ 
167+### Security & Authentication
168+- Session-based auth for web users
169+- API authentication via:
170+ - OAuth2 (Doorkeeper) for third-party apps
171+ - API keys with JWT tokens for direct API access
172+- Scoped permissions system for API access
173+- Strong parameters and CSRF protection throughout
174+ 
175+### Testing Philosophy
176+- Comprehensive test coverage using Rails' built-in Minitest
177+- Fixtures for test data (avoid FactoryBot)
178+- Keep fixtures minimal (2-3 per model for base cases)
179+- VCR for external API testing
180+- System tests for critical user flows (use sparingly)
181+- Test helpers in `test/support/` for common scenarios
182+- Only test critical code paths that significantly increase confidence
183+- Write tests as you go, when required
184+- **API Endpoints require OpenAPI specs** in `spec/requests/api/` for documentation purposes ONLY, not test (uses RSpec + rswag)
185+ 
186+### Performance Considerations
187+- Database queries optimized with proper indexes
188+- N+1 queries prevented via includes/joins
189+- Background jobs for heavy operations
190+- Caching strategies for expensive calculations
191+- Turbo Frames for partial page updates
192+ 
193+### Development Workflow
194+- Feature branches merged to `main`
195+- Docker support for consistent environments
196+- Environment variables via `.env` files
197+- Lookbook for component development (`/lookbook`)
198+- Letter Opener for email preview in development
199+ 
200+## Project Conventions
201+ 
202+### Convention 1: Minimize Dependencies
203+- Push Rails to its limits before adding new dependencies
204+- Strong technical/business reason required for new dependencies
205+- Favor old and reliable over new and flashy
206+ 
207+### Convention 2: Skinny Controllers, Fat Models
208+- Business logic in `app/models/` folder, avoid `app/services/`
209+- Use Rails concerns and POROs for organization
210+- Models should answer questions about themselves: `account.balance_series` not `AccountSeries.new(account).call`
211+ 
212+### Convention 3: Hotwire-First Frontend
213+- **Native HTML preferred over JS components**
214+ - Use `<dialog>` for modals, `<details><summary>` for disclosures
215+- **Leverage Turbo frames** for page sections over client-side solutions
216+- **Query params for state** over localStorage/sessions
217+- **Server-side formatting** for currencies, numbers, dates
218+- **Always use `icon` helper** in `application_helper.rb`, NEVER `lucide_icon` directly
219+ 
220+### Convention 4: Optimize for Simplicity
221+- Prioritize good OOP domain design over performance
222+- Focus performance only on critical/global areas (avoid N+1 queries, mindful of global layouts)
223+ 
224+### Convention 5: Database vs ActiveRecord Validations
225+- Simple validations (null checks, unique indexes) in DB
226+- ActiveRecord validations for convenience in forms (prefer client-side when possible)
227+- Complex validations and business logic in ActiveRecord
228+ 
229+## TailwindCSS Design System
230+ 
231+### Design System Rules
232+- **Always reference `app/assets/tailwind/sure-design-system.css`** for primitives and tokens
233+- **Use functional tokens** defined in design system:
234+ - `text-primary` instead of `text-white`
235+ - `bg-container` instead of `bg-white`
236+ - `border border-primary` instead of `border border-gray-200`
237+- **NEVER create new styles** in design system files without permission
238+- **Always generate semantic HTML**
239+ 
240+## Component Architecture
241+ 
242+### ViewComponent vs Partials Decision Making
243+ 
244+**Use ViewComponents when:**
245+- Element has complex logic or styling patterns
246+- Element will be reused across multiple views/contexts
247+- Element needs structured styling with variants/sizes
248+- Element requires interactive behavior or Stimulus controllers
249+- Element has configurable slots or complex APIs
250+- Element needs accessibility features or ARIA support
251+ 
252+**Use Partials when:**
253+- Element is primarily static HTML with minimal logic
254+- Element is used in only one or few specific contexts
255+- Element is simple template content
256+- Element doesn't need variants, sizes, or complex configuration
257+- Element is more about content organization than reusable functionality
258+ 
259+**Component Guidelines:**
260+- Prefer components over partials when available
261+- Keep domain logic OUT of view templates
262+- Logic belongs in component files, not template files
263+ 
264+### Stimulus Controller Guidelines
265+ 
266+**Declarative Actions (Required):**
267+```erb
268+<!-- GOOD: Declarative - HTML declares what happens -->
269+<div data-controller="toggle">
270+ <button data-action="click->toggle#toggle" data-toggle-target="button">
271+ <%= t("components.transaction_details.show_details") %>
272+ </button>
273+ <div data-toggle-target="content" class="hidden">
274+ <p><%= t("components.transaction_details.amount_label") %>: <%= @transaction.amount %></p>
275+ <p><%= t("components.transaction_details.date_label") %>: <%= @transaction.date %></p>
276+ <p><%= t("components.transaction_details.category_label") %>: <%= @transaction.category.name %></p>
277+ </div>
278+</div>
279+```
280+ 
281+**Example locale file structure (config/locales/en.yml):**
282+```yaml
283+en:
284+ components:
285+ transaction_details:
286+ show_details: "Show Details"
287+ hide_details: "Hide Details"
288+ amount_label: "Amount"
289+ date_label: "Date"
290+ category_label: "Category"
291+```
292+ 
293+**i18n Best Practices:**
294+- Organize keys by feature/component: `components.transaction_details.show_details`
295+- Use descriptive key names that indicate purpose: `show_details` not `button`
296+- Group related translations together in the same namespace
297+- Use interpolation for dynamic content: `t("users.welcome", name: user.name)`
298+- Always update locale files when adding new user-facing strings
299+ 
300+**Controller Best Practices:**
301+- Keep controllers lightweight and simple (< 7 targets)
302+- Use private methods and expose clear public API
303+- Single responsibility or highly related responsibilities
304+- Component controllers stay in component directory, global controllers in `app/javascript/controllers/`
305+- Pass data via `data-*-value` attributes, not inline JavaScript
306+ 
307+## Testing Philosophy
308+ 
309+### General Testing Rules
310+- **ALWAYS use Minitest + fixtures** (NEVER RSpec or factories)
311+- Keep fixtures minimal (2-3 per model for base cases)
312+- Create edge cases on-the-fly within test context
313+- Use Rails helpers for large fixture creation needs
314+ 
315+### Test Quality Guidelines
316+- **Write minimal, effective tests** - system tests sparingly
317+- **Only test critical and important code paths**
318+- **Test boundaries correctly:**
319+ - Commands: test they were called with correct params
320+ - Queries: test output
321+ - Don't test implementation details of other classes
322+ 
323+### Testing Examples
324+ 
325+```ruby
326+# GOOD - Testing critical domain business logic
327+test "syncs balances" do
328+ Holding::Syncer.any_instance.expects(:sync_holdings).returns([]).once
329+ assert_difference "@account.balances.count", 2 do
330+ Balance::Syncer.new(@account, strategy: :forward).sync_balances
331+ end
332+end
333+ 
334+# BAD - Testing ActiveRecord functionality
335+test "saves balance" do
336+ balance_record = Balance.new(balance: 100, currency: "USD")
337+ assert balance_record.save
338+end
339+```
340+ 
341+### Stubs and Mocks
342+- Use `mocha` gem
343+- Prefer `OpenStruct` for mock instances
344+- Only mock what's necessary
345+ 
346+## API Development Guidelines
347+ 
348+### OpenAPI Documentation (MANDATORY)
349+When adding or modifying API endpoints in `app/controllers/api/v1/`, you **MUST** create or update corresponding OpenAPI request specs:
350+ 
351+1. **Location**: `spec/requests/api/v1/{resource}_spec.rb`
352+2. **Framework**: RSpec with rswag for OpenAPI generation
353+3. **Schemas**: Define reusable schemas in `spec/swagger_helper.rb`
354+4. **Generated Docs**: `docs/api/openapi.yaml`
355+ 
356+**Example structure for a new API endpoint:**
357+```ruby
358+# spec/requests/api/v1/widgets_spec.rb
359+require 'swagger_helper'
360+ 
361+RSpec.describe 'API V1 Widgets', type: :request do
362+ path '/api/v1/widgets' do
363+ get 'List widgets' do
364+ tags 'Widgets'
365+ security [ { apiKeyAuth: [] } ]
366+ produces 'application/json'
367+
368+ response '200', 'widgets listed' do
369+ schema '$ref' => '#/components/schemas/WidgetCollection'
370+ run_test!
371+ end
372+ end
373+ end
374+end
375+```
376+ 
377+**Regenerate OpenAPI docs after changes:**
378+```bash
379+RAILS_ENV=test bundle exec rake rswag:specs:swaggerize
380+```
381+ 
382+### Post-commit API consistency (issue #944)
383+After every API endpoint commit, ensure:
384+ 
385+1. **Minitest behavioral coverage** — Add or update tests in `test/controllers/api/v1/{resource}_controller_test.rb`. Use API key and `api_headers` (X-Api-Key). Cover index/show, CRUD where relevant, 401/403/422/404. Do not rely on rswag for behavioral assertions.
386+ 
387+2. **rswag docs-only** — Do not add `expect(...)` or `assert_*` in `spec/requests/api/v1/`. Use `run_test!` only so specs document request/response and regenerate `docs/api/openapi.yaml`.
388+ 
389+3. **Same API key auth in rswag** — Every request spec in `spec/requests/api/v1/` must use the same API key pattern (`ApiKey.generate_secure_key`, `ApiKey.create!(...)`, `let(:'X-Api-Key') { api_key.plain_key }`). Do not use Doorkeeper/OAuth in those specs so generated docs stay consistent.
390+ 
391+Full checklist and pattern: [.cursor/rules/api-endpoint-consistency.mdc](.cursor/rules/api-endpoint-consistency.mdc).
392+ 
393+To verify the implementation: `ruby test/support/verify_api_endpoint_consistency.rb`. To scan the current APIs for violations: `ruby test/support/verify_api_endpoint_consistency.rb --compliance`.
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack