* feat: remember chart period by last selection not user preferences
* feat: schema update
* fix: revert unnecessary parts of schema.rb update
* fix: check period key is valid before setting it
* revert: no database changes and keep the UI setting
* refactor: don't store the default period in the session, just use the user
* fix: migration
The migration uses the User model directly, which loads all current enums
including ui_layout which doesn't exist yet at that point in migration history.
Fix it with raw SQL.
* revert: not relevant to this PR
* fix: use different approach that is compatible with Safari to display table dividers
* fix: add right color for dark theme and remove unnecessary class
* fix(security): sanitize exception messages in API responses (FIX-11)
Replace raw e.message/error.message interpolations in response bodies
with generic error strings, and log class+message server-side. Prevents
leaking internal exception details (stack traces, SQL fragments, record
data) to API clients.
Covers:
- API v1 accounts, categories (index/show), holdings, sync, trades,
transactions (index/show/create/update/destroy), valuations
(show/create/update): replace "Error: #{e.message}" with
"An unexpected error occurred".
- API v1 auth: device-registration rescue paths now log
"[Auth] Device registration failed: ..." and respond with
"Failed to register device".
- WebhooksController#plaid and #plaid_eu: log full error and respond
with "Invalid webhook".
- Settings::ProvidersController: generic user-facing flash alert,
detailed log line with error class + message.
Updates providers_controller_test assertion to match sanitized flash.
* fix(security): address CodeRabbit review
Major — partial-commit on device registration failure:
- Strengthened valid_device_info? to also run MobileDevice's model
validations up-front (device_type inclusion, attribute presence), not
just a flat "are the keys present?" check. A client that sends a bad
device_type ("windows", etc.) is now rejected at the API boundary
BEFORE signup commits any user/family/invite state.
- Wrapped the signup path (user.save + InviteCode.claim + MobileDevice
upsert + token issuance) in ActiveRecord::Base.transaction. A
post-save RecordInvalid from device registration (e.g., racing
uniqueness on device_id) now rolls back the user/invite/family so
clients don't see a partial-account state.
- Rescue branch logs the exception class + message ("#{e.class} - #{e.message}")
for better postmortem debugging, matching the providers controller
pattern.
Nit:
- Tightened providers_controller_test log expectation regex to assert on
both the exception class name AND the message ("StandardError - Database
error"), so a regression that drops either still fails the test.
Tests:
- New: "should reject signup with invalid device_type before committing
any state" — POST /api/v1/auth/signup with device_type="windows"
returns 400 AND asserts no User, MobileDevice, or Doorkeeper::AccessToken
row was created.
Note on SSO path (sso_exchange → issue_mobile_tokens, lines 173/225): the
device_info in those flows comes from Rails.cache (populated by an earlier
request that already passed valid_device_info?), so the pre-validation
covers it indirectly. Wrapping the full SSO account creation (user +
invitation + OidcIdentity + issue_mobile_tokens) in one transaction would
be a meaningful architectural cleanup but is out of scope for this
error-hygiene PR — filed it as a mental note for a follow-up.
* Add Sophtron Provider
* fix syncer test issue
* fix schema wrong merge
* sync #588
* sync code for #588
* fixed a view issue
* modified by comment
* modified
* modifed
* modified
* modified
* fixed a schema issue
* use global subtypes
* add some locales
* fix a safe_return_to_path
* fix exposing raw exception messages issue
* fix a merged issue
* update schema.rb
* fix a schema issue
* fix some issue
* Update bank sync controller to reflect beta status
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
* Rename settings section title to 'Sophtron (alpha)'
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
* Consistency in alpha/beta for Sophtron
* Good PR suggestions from CodeRabbit
---------
Signed-off-by: soky srm <sokysrm@gmail.com>
Signed-off-by: Sophtron Rocky <rocky@sophtron.com>
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: soky srm <sokysrm@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* SimpleFIN: setup UX + same-provider relink + card-replacement detection
Fixes three bugs and adds auto-detection for credit-card fraud replacement.
Bugs:
- Importer: per-institution auth errors no longer flip the whole item to
requires_update. Partial errors stay on sync_stats so other institutions
keep syncing.
- Setup page: new activity badges (recent / dormant / empty / likely-closed)
via SimplefinAccount::ActivitySummary. Likely-closed (dormant + near-zero
balance + prior history) defaults to "skip" in the type picker.
- Relink: link_existing_account allows SimpleFIN to SimpleFIN swaps by
atomically detaching the old AccountProvider inside a transaction. Adds
"Change SimpleFIN account" menu item on linked-account dropdowns.
Feature (credit-card scope only):
- SimplefinItem::ReplacementDetector runs post-sync. Pairs a linked dormant
zero-balance sfa with an unlinked active sfa at the same institution and
account type. Persists suggestions on Sync#sync_stats.
- Inline banner on the SimpleFIN item card prompts relink via CustomConfirm.
Per-pair dismiss button scoped to the current sync (resurfaces on next
sync if still applicable). Auto-suppresses once the relink has landed.
Dev tooling:
- bin/rails simplefin:seed_fraud_scenario[email] creates a realistic broken
pair for manual QA; cleanup_fraud_scenario reverses it.
* Address review feedback on #1493
- ReplacementDetector: symmetric one-to-one matching. Two dormant cards
pointing at the same active card are now both skipped — previously the
detector could emit two suggestions that would clobber each other if
the user accepted both.
- ReplacementDetector: require non-blank institution names on both sides
before matching. Blank-vs-blank was accidentally treated as equal,
risking cross-provider false matches when SimpleFIN omitted org_data.
- ActivitySummary: fall back to "posted" when "transacted_at" is 0
(SimpleFIN's "unknown" sentinel). Integer 0 is truthy in Ruby, so the
previous `|| fallback` short-circuited and ignored posted.
- Controller: dismiss key is now the (dormant, active) pair so dismissing
one candidate for a dormant card doesn't suppress others.
- Helper test: freeze time around "6.hours.ago" and "5.days.ago"
assertions so they don't flake when the suite runs before 06:00.
* Address second review pass on #1493
- ReplacementDetector: canonicalize account_type in one place so filtering
(supported_type?) and matching (type_matches?) agree on "credit card"
vs "credit_card" variants.
- ReplacementDetector: skip candidates with nil current_balance. nil is
"unknown," not "zero" — previously fell back to 0 and passed the near-
zero gate, allowing suggestions without balance evidence.
* EnableBanking: skip CARD-* counterparty in name
# Conflicts:
# test/models/enable_banking_entry/processor_test.rb
# Conflicts:
# test/models/enable_banking_entry/processor_test.rb
* Fix whitespace in remittance_information array
Whitespace added before 'ACME SHOP' in remittance_information.
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
* Fix merchant creation for Wise and prefer remittance for Entry name if counterparty is CARD-XXX
* Fix review
* Handle scalars
* Handle empty strings
* Fix review
* Make truncate not use ellipsis at the end
---------
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: quentinreytinas <quentin@reytinas.fr>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* fix: Restore legacy fallback for credit card balance calculation in Enable Banking
* test: update test following new behavior
* test: keep old test
* fix: use absolute value for balance computation
* feat: Import pending transactions from Enable Banking only if option is enabled in settings
* feat: Move include_pending checks outside of if statement
* chore: code clean-up
* Addressable RegExp Denial of Service
* fix: preserve Generic investment subtypes in account creation form
The .compact call in Investment.subtypes_grouped_for_select removed
all nil values from the region order array, which inadvertently
excluded Generic subtypes (region: nil) from the dropdown for all
users regardless of currency setting.
Replace .compact with conditional logic that preserves nil in the
region order while still handling the user_region placement.
Closes#1446
* Breakage on `main` reverted
* style: fix SpaceInsideArrayLiteralBrackets lint offense
Add spaces inside array literal brackets to match project Rubocop rules.
---------
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: khanhkhanhlele <namkhanh2172@gmail.com>
* feat: Add table-divider class and use it in investments summary section
* fix: manage dark-theme variant
* feat: apply table-divider to other tables
* refactor: use rem instead of px for table-divider class
Ensure accessible_account_ids filtering is applied whenever account scope is provided, including empty arrays, so users with no shared accounts cannot see family-wide transactions.
Also make totals robust when scoped queries return no rows and add regression tests for both visibility and totals behavior with empty accessible account lists.
* Optimize UI in budget
* update locales
* Optimize UI
* optimize suggested_daily_spending
* try over_budget and on_track
* update locale
* optimize
* add budgets_helper.rb
* fix
* hide no buget and no expense sub-catogory
* Optimize
* Optimize button on phone
* Fix Pipelock CI noise
* using section to render both overbudget and onTrack
* hide last ruler
* fix
* update test
---------
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* feat: add currency management for families with enabled currencies
* feat: update currency selection logic and improve accessibility
* feat: update currency preferences to use group moniker in titles
---------
Signed-off-by: Ang Wei Feng (Ted) <hello@tedawf.com>
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
Skip the accessible_account_ids filter when the array is empty, preventing
Rails from creating a "none" relation that causes .take to return nil.
An empty [] is truthy in Ruby, so `if accessible_account_ids` was applying
a WHERE account_id IN () clause that matched nothing.
Fixes#1452
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(enable-banking): refactor error handling and add missing GIN index
* fix(enable-banking): handle wrapped network errors and fix concurrent index migration
* fix(enable-banking): extract network errors to frozen constant
* fix(enable-banking): consolidate error handling and enforce strict localization
* fix(enable-banking): improve sync error handling and fix invalid test status
* test(enable_banking): use OpenStruct instead of mock for provider
* Fix trade drawer header width regression
Wrap the trade header partial in a grow/min-w-0 container inside the custom dialog header row so overview disclosure rows stretch to available width instead of shrinking to content.
Confirmed via git blame that this layout behavior predates PR #1248 and is tied to the custom header flex layout introduced in commit 7ae9077.
* Overlay trade drawer close button to preserve content width
Render the close button absolutely in the custom header instead of as a flex sibling of the full trades header partial. This prevents the button column from shrinking the overview section width and leaving a persistent right-side gutter.
* Fix demo refresh email config lookup
Use indifferent access when reading demo config so the refresh job works whether config keys are strings or symbols. Add a regression test covering symbol-keyed config_for output.
* Remove unnecessary blank line in test file
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
* Binance as securities provider
* Disable twelve data crypto results
* Add logo support and new currency pairs
* FIX importer fallback
* Add price clamping and optiimize retrieval
* Review
* Update adding-a-securities-provider.md
* day gap miss fix
* New fixes
* Brandfetch doesn't support crypto. add new CDN
* Update _investment_performance.html.erb
* Update _balance_sheet.html.erb
Update Balance Sheet to work on iPhone Pro Max without scrolling
Signed-off-by: Derek Brown <browndw4@gmail.com>
* Update _group_weight.html.erb
Make the % icon smaller (5 bars not 10) to fit better on smaller format devices
Signed-off-by: Derek Brown <browndw4@gmail.com>
* Update _group_weight.html.erb
Resolve Codex comment
Signed-off-by: Derek Brown <browndw4@gmail.com>
* Update _balance_sheet.html.erb
Increasing width of the weight column
Signed-off-by: Derek Brown <browndw4@gmail.com>
---------
Signed-off-by: Derek Brown <browndw4@gmail.com>
* feat(select): improve merchant dropdown behavior and placement controls
- add configurable menu_placement strategy to DS::Select (auto/down/up) with safe normalization
forward menu_placement through StyledFormBuilder#collection_select
- force Merchant dropdown to open downward in transaction create and editor forms
- fix select option/search text contrast by applying text-primary in DS select menu
- prevent form jump on open by scrolling only inside dropdown content instead of using scrollIntoView
- clamp internal dropdown scroll to valid bounds for stability
- refactor select controller placement logic for readability (placementMode, clamp) without changing behavior
* set menu_placement=auto for metchant selector