Move rswag gems (rswag-api, rswag-ui, rspec-rails) from test-only to
development+test group so Swagger UI is available in development.
Mount Rswag::Api and Rswag::Ui engines at /api-docs behind a
Rails.env.development? guard. Add initializer to configure the UI
endpoint and API root directory.
https://claude.ai/code/session_011D98PaUEbXpREr8LyQqPvw
* feat(transaction): add support for file attachments using Active Storage
* feat(attachments): implement transaction attachments with upload, show, and delete functionality
* feat(attachments): enhance attachment upload functionality to support multiple files and improved error handling
* feat(attachments): add attachment upload form and display functionality in transaction views
* feat(attachments): implement attachment validation for count, size, and content type; enhance upload form with validation hints
* fix(attachments): use correct UI components
* feat(attachments): Implement Turbo Stream responses for creating and deleting transaction attachments.
* fix(attachments): include auth in activestorage controller
* test(attachments): add test coverage for turbostream and auth
* feat(attachments): extract strings to i18n
* fix(attachments): ensure only newly added attachments are purged when transaction validation fails.
* fix(attachments): validate attachment params
* refactor(attachments): use stimulus declarative actions
* fix(attachments): add auth for other representations
* refactor(attachments): use Browse component for attachment uploads
* fix(attachments): reject empty values on attachment upload
* fix(attachments): hide the upload form if reached max uploads
* fix(attachments): correctly purge only newly added attachments on upload failure
* fix(attachments): ensure attachment count limit is respected within a transaction lock
* fix(attachments): update attachment parameter handling to avoid `ParameterMissing` errors.
* fix(components): adjust icon_only logic for buttonish
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* Add REST API for holdings and trades (Discussion #905)
- Trades: GET index (filter by account_id, account_ids, start_date, end_date),
GET show, POST create (buy/sell with security_id or ticker), PATCH update,
DELETE destroy. Create restricted to accounts that support trades (investment
or crypto exchange). Uses existing Trade::CreateForm for creation.
- Holdings: GET index (filter by account_id, account_ids, date, start_date,
end_date, security_id), GET show. Read-only; scoped to family.
- Auth: read scope for index/show; write scope for create/update/destroy.
- Responses: JSON via jbuilder (trade: id, date, amount, qty, price, account,
security, category; holding: id, date, qty, price, amount, account, security,
avg_cost). Pagination for index endpoints (page, per_page).
Co-authored-by: Cursor <cursoragent@cursor.com>
* API v1 holdings & trades: validation, docs, specs
- Holdings: validate date params, return 400 for invalid dates (parse_date!)
- Trades: validate start_date/end_date, return 422 for invalid dates
- Trades: accept buy/sell and inflow/outflow in update (trade_sell_from_type_or_nature?)
- Trades view: nil guard for trade.security
- Trades apply_filters: single join(:entry) when filtering
- OpenAPI: add Trade/TradeCollection schemas, ErrorResponse.errors
- Add spec/requests/api/v1/holdings_spec.rb and trades_spec.rb (rswag)
- Regenerate docs/api/openapi.yaml
Co-authored-by: Cursor <cursoragent@cursor.com>
* CI: fix Brakeman and test rate-limit failures
- Disable Rack::Attack in test (use existing enabled flag) so parallel
API tests no longer hit 429 from shared api_ip throttle
- Add Brakeman ignore for trades_controller trade_params mass-assignment
(account_id/security_id validated in create/update)
- Trades/holdings API and OpenAPI spec updates
Co-authored-by: Cursor <cursoragent@cursor.com>
* Trades: partial qty/price update fallback; fix PATCH OpenAPI schema
- Fall back to existing trade qty/price when only one is supplied so sign
normalisation and amount recalculation always run
- OpenAPI: remove top-level qty, price, investment_activity_label,
category_id from PATCH body; document entryable_attributes only
Co-authored-by: Cursor <cursoragent@cursor.com>
* Trades: fix update/DELETE OpenAPI and avoid sell-trade corruption
- Only run qty/price normalisation when client sends qty or price; preserve
existing trade direction when type/nature omitted
- OpenAPI: remove duplicate PATCH path param; add 422 for PATCH; document
DELETE 200 body (DeleteResponse)
Co-authored-by: Cursor <cursoragent@cursor.com>
* API: flat trade update params, align holdings errors, spec/OpenAPI fixes
- Trades update: accept flat params (qty, price, type, etc.), build
entryable_attributes in build_entry_params_for_update (match transactions)
- Holdings: ArgumentError → 422 validation_failed; parse_date!(value, name)
with safe message; extract render_validation_error, log_and_render_error
- Specs: path id required (trades, holdings); trades delete 200 DeleteResponse;
remove holdings 500; trades update body flat; holdings 422 invalid date
- OpenAPI: PATCH trade request body flat
Co-authored-by: Cursor <cursoragent@cursor.com>
* OpenAPI: add 422 invalid date filter to holdings index
Co-authored-by: Cursor <cursoragent@cursor.com>
* API consistency and RSwag doc-only fixes
- Trades: use render_validation_error in all 4 validation paths; safe_per_page_param case/when
- Holdings: set_holding to family.holdings.find; price as Money.format in API; safe_per_page_param case/when
- Swagger: Holding qty/price descriptions (Quantity of shares held, Formatted price per share)
- RSwag: trades delete and valuations 201 use bare run_test! (documentation only, no expect)
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix index-vs-show visibility inconsistencies and preserve custom activity labels
- Add account status filter to set_holding to match index behavior
- Add visible scope to set_trade to match index behavior
- Preserve existing investment_activity_label when updating qty/price
Co-authored-by: Cursor <cursoragent@cursor.com>
* Trades: clearer validation for non-numeric qty/price
Return 'must be valid numbers' when qty or price is non-numeric (e.g. abc)
instead of misleading 'must be present and positive'.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: mkdev11 <jaysmth689+github@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: Protect demo monitoring API key from deletion
- Add DEMO_MONITORING_KEY constant to ApiKey model
- Add `demo_monitoring_key?` method to identify the monitoring key
- Add `visible` scope to exclude monitoring key from UI queries
- Update controller to use `visible` scope, hiding the monitoring key
- Prevent revocation of the monitoring key with explicit error handling
- Update Demo::Generator to use the shared constant
Users on the demo instance can still create their own API keys,
but cannot see or delete the monitoring key used for uptime checks.
https://claude.ai/code/session_01RQFsw39K7PB5kztboVdBdB
* Linter
* Protect demo monitoring API key from deletion
* Use monitoring source for demo API key
* Add test for demo monitoring revoke guard
* Disable Rack::Attack in test and development
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add SSL_CA_FILE and SSL_VERIFY environment variables to support self-signed certificates in self-hosted environments
* fix: NoMethodError by defining SSL helper methods before configure block executes
* refactor: Refactor SessionsController to use shared SslConfigurable module and simplify SSL initializer redundant checks
* refactor: improve SSL configuration robustness and error detection accuracy
* fix:HTTParty SSL options, add file validation guards, prevent Tempfile GC, and redact URLs in error logs
* fix: Fix SSL concern indentation and stub Simplefin POST correctly in tests
* fix: normalize ssl_verify to always return boolean instead of nil
* fix: solve failing SimpleFin test
* refactor: trim unused error-handling code from SslConfigurable, replace Tempfile with fixed-path CA bundle, fix namespace pollution in initializers, and add unit tests for core SSL configuration and Langfuse CRL callback.
* fix: added require ileutils in the initializer and require ostruct in the test file.
* fix: solve autoload conflict that broke provider loading, validate all certs in PEM bundles, and add missing requires.
* feat: Add CORS support for Flutter mobile client
Add rack-cors gem and configure CORS for API and OAuth endpoints
to enable cross-origin requests from mobile clients and other
external applications.
https://claude.ai/code/session_01RJ6MKLkjBv7x5AQLEUn8AF
* feat: Add /sessions/* to CORS for webview authentication
Enable CORS for session endpoints to support webview-based
authentication flows in the Flutter mobile client.
https://claude.ai/code/session_01RJ6MKLkjBv7x5AQLEUn8AF
* test: Add integration tests for CORS configuration
Test that CORS middleware is configured and returns proper headers
for API, OAuth, and session endpoints including preflight requests.
https://claude.ai/code/session_01RJ6MKLkjBv7x5AQLEUn8AF
* Gemfile.lock
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix: Register sync_all_accounts cron job on Sidekiq startup
AutoSyncScheduler.sync! was only called when changing settings in the UI,
so the nightly sync job was never registered. Now it's initialized when
Sidekiq starts, ensuring accounts sync nightly as configured.
* Utilize existing configure_server block
---------
Co-authored-by: Pieter <ptr@arcsec.org>
The encryption initializer previously only supported environment variables
in self-hosted mode. In managed mode, it expected encryption credentials
to exist in Rails.application.credentials, which would cause boot failures
if they were missing.
This change updates the encryption configuration to support environment
variables in both managed and self-hosted modes:
- Environment variables (ACTIVE_RECORD_ENCRYPTION_*) now work in both modes
- Priority: env vars > auto-generation (self-hosted only) > credentials
- Updated documentation in .env.example and Helm chart README
This allows managed mode deployments to provide encryption keys via
environment variables instead of requiring Rails credentials.
Co-authored-by: Claude <noreply@anthropic.com>
* Introduce SnapTrade integration with models, migrations, views, and activity processing logic.
* Refactor SnapTrade activities processing: improve activity fetching flow, handle pending states, and update UI elements for enhanced user feedback.
* Update Brakeman ignore file to include intentional redirect for SnapTrade OAuth portal.
* Refactor SnapTrade models, views, and processing logic: add currency extraction helper, improve pending state handling, optimize migration checks, and enhance user feedback in UI.
* Remove encryption for SnapTrade `snaptrade_user_id`, as it is an identifier, not a secret.
* Introduce `SnaptradeConnectionCleanupJob` to asynchronously handle SnapTrade connection cleanup and improve i18n for SnapTrade item status messages.
* Update SnapTrade encryption: make `snaptrade_user_secret` non-deterministic to enhance security.
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>