* Fix budget donut chart hiding center content on segment hover
* Preserve segment hover in center unless leaving the unused arc
The unused arc has no interactive link in its center template, so
moving from it into the center content should restore default content(including the Edit Budget link) immediately. All other segments have a DS::Link in their center template that must remain clickable after the cursor moves from the arc into the center.
Pass the D3 datum into the mouseleave handler to read d.data.id, then clear hover when either (a) the departing segment is the unused arc, or (b) the cursor is not heading into contentContainerTarget.
* fix(localization): update API usage instructions to include product name placeholder
* Fix: Update show and created views to use dynamic usage_instructions per CodeRabbit
* fix: update usage instructions translation key for API key usage
* 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>