* Enhance logging in search_family_files.rb
Added logging for search parameters and results in SearchFamilyFiles.
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
* Log level should be `debug` not `warn` here
* Unguarded `trace&.update` patterns
* API concernts from CodeRabbit
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
* Display user admins grouped
* Start family/groups collapsed
* Sort by number of transactions
* Display subscription status
* Fix tests
* Use Stimulus
Both Uncategorized and Other Investments are synthetic categories with
id=nil. When expense_totals_by_category indexes by category.id, Other
Investments overwrites Uncategorized at the nil key, causing uncategorized
actual spending to always return 0.
Use category.name as fallback key (id || name) to differentiate the two
synthetic categories in all hash builders and lookup sites.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add new Date field when creating a new Account
* Fix german translation
* Update app/controllers/concerns/accountable_resource.rb
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>
* Add missing opening_balance:date to update_params
* Change label text
---------
Signed-off-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* feat: add new UI component to display dropdown select with filter
* feat: use new dropdown componet for category selection in transactions
* feat: improve dropdown controller
* feat: Add checkbox indicator to highlight selected element in list
* feat: add possibility to define dropdown without search
* feat: initial implementation of variants
* feat: Add default color for dropdown menu
* feat: add "icon" variant for dropdown
* refactor: component + controller refactoring
* refactor: view + component
* fix: adjust min width in selection for mobile
* feat: refactor collection_select method to use new filter dropdown component
* fix: compute fixed position for dropdown
* feat: controller improvements
* lint issues
* feat: add dot color if no icon is available
* refactor: controller refactor + update naming for variant from icon to logo
* fix: set width to 100% for select dropdown
* feat: add variant to collection_select in new transaction form
* fix: typo in placeholder value
* fix: add back include_blank property
* refactor: rename component from FilterDropdown to Select
* fix: translate placeholder and keep value_method and text_method
* fix: remove duplicate variable assignment
* fix: translate placeholder
* fix: verify color format
* fix: use right autocomplete value
* fix: selection issue + controller adjustments
* fix: move calls to startAutoUpdate and stopAutoUpdate
* Update app/javascript/controllers/select_controller.js
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Alessio Cappa <104093777+alessiocappa@users.noreply.github.com>
* fix: add aria-labels
* fix: pass html_options to DS::Select
* fix: unnecessary closing tag
* fix: use offsetvalue for position checks
* fix: use right classes for dropdown transitions
* include options[:prompt] in placeholder init
* fix: remove unused locale key
* fix: Emit a native change event after updating the input value.
* fix: Guard against negative maxHeight in constrained layouts.
* fix: Update test
* fix: lint issues
* Update test/system/transfers_test.rb
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Alessio Cappa <104093777+alessiocappa@users.noreply.github.com>
* Update test/system/transfers_test.rb
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Alessio Cappa <104093777+alessiocappa@users.noreply.github.com>
* refactor: move CSS class for button select form in maybe-design-system.css
---------
Signed-off-by: Alessio Cappa <104093777+alessiocappa@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* fix: extend width for holdings table in reports
* fix: use right cols for header
* fix: reduce padding on sections
* fix: update holdings table display on dashboard
* feat: set max width for holding name
* fix: remove fixed width on last column
* Update app/views/pages/dashboard/_investment_summary.html.erb
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Alessio Cappa <104093777+alessiocappa@users.noreply.github.com>
* fix: add check on holding.ticker to ensure it's present
---------
Signed-off-by: Alessio Cappa <104093777+alessiocappa@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Feat: Implement manual sync prices functionality and enhance holdings display
* Feat: Enhance sync prices functionality with error handling and update UI components
* Feat: Update sync prices error handling and enhance Spanish locale messages
* Fix: Address CodeRabbit review feedback
- Set fallback @provider_error when prices_updated == 0 so turbo stream
never fails silently without a visible error message
- Move attr_reader :provider_error to class header in Price::Importer
for conventional placement alongside other attribute declarations
- Precompute @last_price_updated in controller (show + sync_prices)
instead of running a DB query directly inside ERB templates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Replace bare rescue with explicit exception handling in turbo stream view
Bare `rescue` silently swallows all exceptions, making debugging impossible.
Match the pattern already used in show.html.erb: rescue ActiveRecord::RecordInvalid
explicitly, then catch StandardError with logging (message + backtrace) before
falling back to the unknown label.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Update test assertion to expect actual provider error message
The stub returns "Yahoo Finance rate limit exceeded" as the provider error.
After the @provider_error fallback fix, the controller now correctly surfaces
the real provider error when present (using .presence || fallback), so the
flash[:alert] is the actual error string, not the generic fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Assert scoped security_ids in sync_prices materializer test
Replace loose stub with constructor expectation to verify that
Balance::Materializer is instantiated with the single-security scope.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix: Assert holding remap in remap_security test
Add assertion that @holding.security_id is updated to the target
security after remap, covering the core command outcome.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix: CI test failure - Update disconnect external assistant test to use env overrides
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add dynamic assistant icon: OpenClaw lobster SVG for external assistant
When a family (or installation via ASSISTANT_TYPE env var) uses the
"external" assistant, the AI avatar now shows a lobster/claw icon
(claw.svg / claw-dark.svg) instead of the default builtin AI icon.
The icon switches dynamically based on the current configuration.
https://claude.ai/code/session_01Wt7HiFypk3Nbs8z2hAkmkG
* Update app/views/chats/_ai_avatar.html.erb
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
---------
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Expand AI docs: architecture, MCP, external assistant setup, troubleshooting
- Add architecture overview explaining two independent AI pipelines
(chat assistant vs auto-categorization)
- Document MCP callback endpoint (JSON-RPC 2.0, auth, available tools)
- Add OpenClaw gateway configuration example
- Add Kubernetes network policy guidance (targetPort vs servicePort)
- Add Pipelock notes (mcpToolPolicy, NO_PROXY behavior)
- Add troubleshooting for "Failed to generate response" with external assistant
- Fix stale function list (4 tools -> 7)
- Fix incorrect env-vs-UI precedence statement
- Fix em-dashes in existing content
* Fix troubleshooting curl to use pod env vars
Use sh -c so $EXTERNAL_ASSISTANT_TOKEN and $EXTERNAL_ASSISTANT_URL
expand inside the pod, not on the local shell.
Use `# pipelock:ignore Credential in URL` on the specific false
positive line instead of excluding all of client.rb from scanning.
The rest of the file is now scanned normally.
* Complete Spanish (es) translations across all locale files
Add missing translations for 44 locale files covering views, models,
mailers, and defaults. Includes 18 new es.yml files and updates to
26 existing ones.
* Small fixes
* Fix CodeRabbit comments
The `subcategories` method queries `WHERE parent_id = category.id`, but
for the synthetic uncategorized budget category, `category.id` is nil.
This caused `WHERE parent_id IS NULL` to match ALL top-level categories,
making them appear as subcategories of uncategorized. This inflated
actual_spending and produced a large negative available_to_spend.
Add a nil guard on category.id to return an empty relation for synthetic
categories.
Fixes#819
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add budget rollover: copy from previous month
When navigating to an uninitialized budget month, show a prompt
offering to copy amounts from the most recent initialized budget.
Copies budgeted_spending, expected_income, and all matching category
allocations. Also fixes over-allocation warning showing on uninitialized
budgets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Redirect copy_previous to categories wizard for review
Matches the normal budget setup flow (edit → categories → show)
so users can review/tweak copied allocations before confirming.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address code review: eager-load categories, guard against overwrite
- Add .includes(:budget_categories) to most_recent_initialized_budget
to avoid N+1 when copy_from! iterates source categories
- Guard copy_previous action against overwriting already-initialized
budgets (prevents crafted POST from clobbering existing data)
- Add i18n key for already_initialized flash message
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add invariant guards to copy_from! for defensive safety
Validate that source budget belongs to the same family and precedes
the target budget before copying. Protects against misuse from
other callers beyond the controller.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix button overflow on small screens in copy previous prompt
Stack buttons vertically on mobile, side-by-side on sm+ breakpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Transfers created before PR #924 have kind='investment_contribution'
but category_id=NULL because auto-categorization was only added to
Transfer::Creator, not the other code paths. PR #924 fixed it going
forward. This migration catches the old ones.
Only updates transactions where category_id IS NULL so it never
overwrites user choices. Skips families without the category.
* feat(helm): add Pipelock ConfigMap, scanning config, and consolidate compose
- Add ConfigMap template rendering DLP, response scanning, MCP input/tool
scanning, and forward proxy settings from values
- Mount ConfigMap as /etc/pipelock/pipelock.yaml volume in deployment
- Add checksum/config annotation for automatic pod restart on config change
- Gate HTTPS_PROXY/HTTP_PROXY env injection on forwardProxy.enabled (skip
in MCP-only mode)
- Use hasKey for all boolean values to prevent Helm default swallowing false
- Single source of truth for ports (forwardProxy.port/mcpProxy.port)
- Pipelock-specific imagePullSecrets with fallback to app secrets
- Merge standalone compose.example.pipelock.yml into compose.example.ai.yml
- Add pipelock.example.yaml for Docker Compose users
- Add exclude-paths to CI workflow for locale file false positives
* Add external assistant support (OpenAI-compatible SSE proxy)
Allow self-hosted instances to delegate chat to an external AI agent
via an OpenAI-compatible streaming endpoint. Configurable per-family
through Settings UI or ASSISTANT_TYPE env override.
- Assistant::External::Client: SSE streaming HTTP client (no new gems)
- Settings UI with type selector, env lock indicator, config status
- Helm chart and Docker Compose env var support
- 45 tests covering client, config, routing, controller, integration
* Add session key routing, email allowlist, and config plumbing
Route to the actual OpenClaw session via x-openclaw-session-key header
instead of creating isolated sessions. Gate external assistant access
behind an email allowlist (EXTERNAL_ASSISTANT_ALLOWED_EMAILS env var).
Plumb session_key and allowedEmails through Helm chart, compose, and
env template.
* Add HTTPS_PROXY support to External::Client for Pipelock integration
Net::HTTP does not auto-read HTTPS_PROXY/HTTP_PROXY env vars (unlike
Faraday). Explicitly resolve proxy from environment in build_http so
outbound traffic to the external assistant routes through Pipelock's
forward proxy when enabled. Respects NO_PROXY for internal hosts.
* Add UI fields for external assistant config (Setting-backed with env fallback)
Follow the same pattern as OpenAI settings: database-backed Setting
fields with env var defaults. Self-hosters can now configure the
external assistant URL, token, and agent ID from the browser
(Settings > Self-Hosting > AI Assistant) instead of requiring env vars.
Fields disable when the corresponding env var is set.
* Improve external assistant UI labels and add help text
Change placeholder to generic OpenAI-compatible URL pattern. Add help
text under each field explaining where the values come from: URL from
agent provider, token for authentication, agent ID for multi-agent
routing.
* Add external assistant docs and fix URL help text
Add External AI Assistant section to docs/hosting/ai.md covering setup
(UI and env vars), how it works, Pipelock security scanning, access
control, and Docker Compose example. Drop "chat completions" jargon
from URL help text.
* Harden external assistant: retry logic, disconnect UI, error handling, and test coverage
- Add retry with backoff for transient network errors (no retry after streaming starts)
- Add disconnect button with confirmation modal in self-hosting settings
- Narrow rescue scope with fallback logging for unexpected errors
- Safe cleanup of partial responses on stream interruption
- Gate ai_available? on family assistant_type instead of OR-ing all providers
- Truncate conversation history to last 20 messages
- Proxy-aware HTTP client with NO_PROXY support
- Sanitize protocol to use generic headers (X-Agent-Id, X-Session-Key)
- Full test coverage for streaming, retries, proxy routing, config, and disconnect
* Exclude external assistant client from Pipelock scan-diff
False positive: `@token` instance variable flagged as "Credential in URL".
Temporary workaround until Pipelock supports inline suppression.
* Address review feedback: NO_PROXY boundary fix, SSE done flag, design tokens
- Fix NO_PROXY matching to require domain boundary (exact match or .suffix),
case-insensitive. Prevents badexample.com matching example.com.
- Add done flag to SSE streaming so read_body stops after [DONE]
- Move MAX_CONVERSATION_MESSAGES to class level
- Use bg-success/bg-destructive design tokens for status indicators
- Add rationale comment for pipelock scan exclusion
- Update docs last-updated date
* Address second round of review feedback
- Allowlist email comparison is now case-insensitive and nil-safe
- Cap SSE buffer at 1 MB to prevent memory blowup from malformed streams
- Don't expose upstream HTTP response body in user-facing errors (log it instead)
- Fix frozen string warning on buffer initialization
- Fix "builtin" typo in docs (should be "built-in")
* Protect completed responses from cleanup, sanitize error messages
- Don't destroy a fully streamed assistant message if post-stream
metadata update fails (only cleanup partial responses)
- Log raw connection/HTTP errors internally, show generic messages
to users to avoid leaking network/proxy details
- Update test assertions for new error message wording
* Fix SSE content guard and NO_PROXY test correctness
Use nil check instead of present? for SSE delta content to preserve
whitespace-only chunks (newlines, spaces) that can occur in code output.
Fix NO_PROXY test to use HTTP_PROXY matching the http:// client URL so
the proxy resolution and NO_PROXY bypass logic are actually exercised.
* Forward proxy credentials to Net::HTTP
Pass proxy_uri.user and proxy_uri.password to Net::HTTP.new so
authenticated proxies (http://user:pass@host:port) work correctly.
Without this, credentials parsed from the proxy URL were silently
dropped. Nil values are safe as positional args when no creds exist.
* Update pipelock integration to v0.3.1 with full scanning config
Bump Helm image tag from 0.2.7 to 0.3.1. Add missing security
sections to both the Helm ConfigMap and compose example config:
mcp_tool_policy, mcp_session_binding, and tool_chain_detection.
These protect the /mcp endpoint against tool injection, session
hijacking, and multi-step exfiltration chains.
Add version and mode fields to config files. Enable include_defaults
for DLP and response scanning to merge user patterns with the 35
built-in patterns. Remove redundant --mode CLI flag from the Helm
deployment template since mode is now in the config file.
* Pipelock Helm hardening + docs for external assistant and pipelock
Helm templates:
- ServiceMonitor for Prometheus scraping on /metrics (proxy port)
- Ingress template for MCP reverse proxy (external AI agent access)
- PodDisruptionBudget with minAvailable/maxUnavailable mutual exclusion
- topologySpreadConstraints on Deployment
- Structured logging config (format, output, include_allowed/blocked)
- extraConfig escape hatch for additional pipelock.yaml sections
- requireForExternalAssistant guard (fails when assistant enabled without pipelock)
- Component label on Service metadata for ServiceMonitor targeting
- NOTES.txt pipelock section with health, access, security, metrics info
- Bump pipelock image tag 0.3.1 -> 0.3.2
- Fix: rename _asserts.tpl -> asserts.tpl (Helm skipped _ prefixed file)
Documentation:
- Helm chart README: full Pipelock section
- docs/hosting/pipelock.md: dedicated hosting guide (Docker + Kubernetes)
- docs/hosting/docker.md: AI features section (external assistant, pipelock)
- .env.example: external assistant and MCP env vars
Infra:
- Chart.lock pinning dependency versions
- .gitignore for vendored subchart tarballs
* Fix bot comments: quote ingress host, fix sidecar wording, add code block lang
* Fail fast when pipelock ingress enabled with empty hosts
* Fail fast when pipelock ingress host has empty paths
* Messed up the conflict merge
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* feat(helm): add Pipelock ConfigMap, scanning config, and consolidate compose
- Add ConfigMap template rendering DLP, response scanning, MCP input/tool
scanning, and forward proxy settings from values
- Mount ConfigMap as /etc/pipelock/pipelock.yaml volume in deployment
- Add checksum/config annotation for automatic pod restart on config change
- Gate HTTPS_PROXY/HTTP_PROXY env injection on forwardProxy.enabled (skip
in MCP-only mode)
- Use hasKey for all boolean values to prevent Helm default swallowing false
- Single source of truth for ports (forwardProxy.port/mcpProxy.port)
- Pipelock-specific imagePullSecrets with fallback to app secrets
- Merge standalone compose.example.pipelock.yml into compose.example.ai.yml
- Add pipelock.example.yaml for Docker Compose users
- Add exclude-paths to CI workflow for locale file false positives
* Add external assistant support (OpenAI-compatible SSE proxy)
Allow self-hosted instances to delegate chat to an external AI agent
via an OpenAI-compatible streaming endpoint. Configurable per-family
through Settings UI or ASSISTANT_TYPE env override.
- Assistant::External::Client: SSE streaming HTTP client (no new gems)
- Settings UI with type selector, env lock indicator, config status
- Helm chart and Docker Compose env var support
- 45 tests covering client, config, routing, controller, integration
* Add session key routing, email allowlist, and config plumbing
Route to the actual OpenClaw session via x-openclaw-session-key header
instead of creating isolated sessions. Gate external assistant access
behind an email allowlist (EXTERNAL_ASSISTANT_ALLOWED_EMAILS env var).
Plumb session_key and allowedEmails through Helm chart, compose, and
env template.
* Add HTTPS_PROXY support to External::Client for Pipelock integration
Net::HTTP does not auto-read HTTPS_PROXY/HTTP_PROXY env vars (unlike
Faraday). Explicitly resolve proxy from environment in build_http so
outbound traffic to the external assistant routes through Pipelock's
forward proxy when enabled. Respects NO_PROXY for internal hosts.
* Add UI fields for external assistant config (Setting-backed with env fallback)
Follow the same pattern as OpenAI settings: database-backed Setting
fields with env var defaults. Self-hosters can now configure the
external assistant URL, token, and agent ID from the browser
(Settings > Self-Hosting > AI Assistant) instead of requiring env vars.
Fields disable when the corresponding env var is set.
* Improve external assistant UI labels and add help text
Change placeholder to generic OpenAI-compatible URL pattern. Add help
text under each field explaining where the values come from: URL from
agent provider, token for authentication, agent ID for multi-agent
routing.
* Add external assistant docs and fix URL help text
Add External AI Assistant section to docs/hosting/ai.md covering setup
(UI and env vars), how it works, Pipelock security scanning, access
control, and Docker Compose example. Drop "chat completions" jargon
from URL help text.
* Harden external assistant: retry logic, disconnect UI, error handling, and test coverage
- Add retry with backoff for transient network errors (no retry after streaming starts)
- Add disconnect button with confirmation modal in self-hosting settings
- Narrow rescue scope with fallback logging for unexpected errors
- Safe cleanup of partial responses on stream interruption
- Gate ai_available? on family assistant_type instead of OR-ing all providers
- Truncate conversation history to last 20 messages
- Proxy-aware HTTP client with NO_PROXY support
- Sanitize protocol to use generic headers (X-Agent-Id, X-Session-Key)
- Full test coverage for streaming, retries, proxy routing, config, and disconnect
* Exclude external assistant client from Pipelock scan-diff
False positive: `@token` instance variable flagged as "Credential in URL".
Temporary workaround until Pipelock supports inline suppression.
* Address review feedback: NO_PROXY boundary fix, SSE done flag, design tokens
- Fix NO_PROXY matching to require domain boundary (exact match or .suffix),
case-insensitive. Prevents badexample.com matching example.com.
- Add done flag to SSE streaming so read_body stops after [DONE]
- Move MAX_CONVERSATION_MESSAGES to class level
- Use bg-success/bg-destructive design tokens for status indicators
- Add rationale comment for pipelock scan exclusion
- Update docs last-updated date
* Address second round of review feedback
- Allowlist email comparison is now case-insensitive and nil-safe
- Cap SSE buffer at 1 MB to prevent memory blowup from malformed streams
- Don't expose upstream HTTP response body in user-facing errors (log it instead)
- Fix frozen string warning on buffer initialization
- Fix "builtin" typo in docs (should be "built-in")
* Protect completed responses from cleanup, sanitize error messages
- Don't destroy a fully streamed assistant message if post-stream
metadata update fails (only cleanup partial responses)
- Log raw connection/HTTP errors internally, show generic messages
to users to avoid leaking network/proxy details
- Update test assertions for new error message wording
* Fix SSE content guard and NO_PROXY test correctness
Use nil check instead of present? for SSE delta content to preserve
whitespace-only chunks (newlines, spaces) that can occur in code output.
Fix NO_PROXY test to use HTTP_PROXY matching the http:// client URL so
the proxy resolution and NO_PROXY bypass logic are actually exercised.
* Forward proxy credentials to Net::HTTP
Pass proxy_uri.user and proxy_uri.password to Net::HTTP.new so
authenticated proxies (http://user:pass@host:port) work correctly.
Without this, credentials parsed from the proxy URL were silently
dropped. Nil values are safe as positional args when no creds exist.
* Update pipelock integration to v0.3.1 with full scanning config
Bump Helm image tag from 0.2.7 to 0.3.1. Add missing security
sections to both the Helm ConfigMap and compose example config:
mcp_tool_policy, mcp_session_binding, and tool_chain_detection.
These protect the /mcp endpoint against tool injection, session
hijacking, and multi-step exfiltration chains.
Add version and mode fields to config files. Enable include_defaults
for DLP and response scanning to merge user patterns with the 35
built-in patterns. Remove redundant --mode CLI flag from the Helm
deployment template since mode is now in the config file.
* feat(helm): add Pipelock ConfigMap, scanning config, and consolidate compose
- Add ConfigMap template rendering DLP, response scanning, MCP input/tool
scanning, and forward proxy settings from values
- Mount ConfigMap as /etc/pipelock/pipelock.yaml volume in deployment
- Add checksum/config annotation for automatic pod restart on config change
- Gate HTTPS_PROXY/HTTP_PROXY env injection on forwardProxy.enabled (skip
in MCP-only mode)
- Use hasKey for all boolean values to prevent Helm default swallowing false
- Single source of truth for ports (forwardProxy.port/mcpProxy.port)
- Pipelock-specific imagePullSecrets with fallback to app secrets
- Merge standalone compose.example.pipelock.yml into compose.example.ai.yml
- Add pipelock.example.yaml for Docker Compose users
- Add exclude-paths to CI workflow for locale file false positives
* Add CHANGELOG entry for Pipelock security proxy integration
* Missed v0.6.8 release
---------
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* Fix: use cookie/crumb auth in healthy? chart endpoint check
The health check was calling /v8/finance/chart/AAPL via the plain
unauthenticated client. Yahoo Finance requires cookie + crumb
authentication on the chart endpoint, so the health check would
fail even when credentials are valid. Updated healthy? to use
fetch_cookie_and_crumb + authenticated_client, consistent with
fetch_security_prices and fetch_chart_data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: add cookie/crumb auth to all /v8/finance/chart/ calls
fetch_security_prices and fetch_chart_data (used for exchange rates)
were calling the chart endpoint without cookie/crumb authentication,
inconsistent with healthy? and fetch_security_info. Added auth to both,
including the same retry-on-Unauthorized pattern already used in
fetch_security_info.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update user-agent strings in yahoo_finance.rb
Updated user-agent strings to reflect current browser versions
Signed-off-by: Serge L <serge@souritech.ca>
* Fix: Add stale-crumb retry to healthy? and fetch_chart_data
Yahoo Finance returns 200 OK with {"chart":{"error":{"code":"Unauthorized"}}}
when a cached crumb expires server-side. Both healthy? and fetch_chart_data
now mirror the retry pattern already in fetch_security_prices: detect the
Unauthorized body, clear the crumb cache, fetch fresh credentials, and
retry the request once. Adds a test for the healthy? retry path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Refactor: Extract fetch_authenticated_chart helper to DRY crumb retry logic
The cookie/crumb fetch + stale-crumb retry pattern was duplicated across
healthy?, fetch_security_prices, and fetch_chart_data. Extract it into a
single private fetch_authenticated_chart(symbol, params) helper that
centralizes the retry logic; all three call sites now delegate to it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Catch JSON::ParserError in fetch_chart_data rescue clause
After moving JSON.parse inside fetch_authenticated_chart, a malformed
Yahoo response would throw JSON::ParserError through fetch_chart_data's
rescue Faraday::Error, breaking the inverse currency pair fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Raise AuthenticationError if retry still returns Unauthorized
After refreshing the crumb and retrying, if Yahoo still returns an
Unauthorized error body the helper now raises AuthenticationError instead
of silently returning the error payload. This prevents callers from
misinterpreting a persistent auth failure as missing chart data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Raise AuthenticationError after failed retry in fetch_security_info
Mirrors the same post-retry Unauthorized check added to fetch_authenticated_chart.
Without this, a persistent auth failure on the quoteSummary endpoint would
surface as a generic "No security info found" error instead of an AuthenticationError.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Signed-off-by: Serge L <serge@souritech.ca>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The wizard layout header lacked safe-area-inset-top padding, causing
the back arrow and X button to sit under the system status bar in PWA
standalone mode. All other layouts already account for this.
Co-authored-by: Claude <noreply@anthropic.com>
The polling controller was requesting turbo_stream format but only an
HTML template exists. Fix the Accept header to request text/html and
handle both formats in the controller.
* feat: Add tag badge in filter window
* fix: validate Tag color attribute as hex format and increase transparency mix in border color
* fix: use fallback for tag color
* fix/qol: Add wich Callback URL to use to the Enable Banking Instructions
* CodeRabbit suggestion
* CodeRabbit suggestion
* Skip CI failure on findings
---------
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* fix: Update PWA icons to use current logo (#997)
Replace outdated android-chrome-192x192.png and logo-pwa.png with the
current logo. The old icons showed the previous branding (cyan border /
old logomark) which appeared when creating web shortcuts on smartphones.
Also add the 192x192 icon entry to the PWA manifest for better Android
home screen icon support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Replace transparent background with solid #F9F9F9 in 192x192 PWA icon
The android-chrome-192x192.png had an RGBA transparent background which
can cause display issues on Android home-screen shortcuts. Regenerated
with a solid #F9F9F9 background to match theme_color/background_color
in the PWA manifest and the 512x512 icon.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace direct trace.update calls with client trace upserts so OpenAI provider is compatible with langfuse-ruby 0.1.6 behavior. Add richer warning logs that include full exception details for trace creation, trace upserts, and generation logging failures. Add tests for client-based trace upserts and detailed error logging.
* Add MCP server endpoint for external AI assistants
Expose Sure's Assistant::Function tools via JSON-RPC 2.0 at POST /mcp,
enabling external AI clients (Claude, GPT, etc.) to query financial data
through the Model Context Protocol.
- Bearer token auth via MCP_API_TOKEN / MCP_USER_EMAIL env vars
- JSON-RPC 2.0 with proper id threading, notification handling (204)
- Transient session (sessions.build) to prevent impersonation leaks
- Centralize function_classes in Assistant module
- Docker Compose example with Pipelock forward proxy
- 18 integration tests with scoped env (ClimateControl)
* Update compose for full Pipelock MCP reverse proxy integration
Use Pipelock's --mcp-listen/--mcp-upstream flags (PR #127) to run
bidirectional MCP scanning in the same container as the forward proxy.
External AI clients connect to port 8889, Pipelock scans requests
(DLP, injection, tool policy) and responses (injection, tool poisoning)
before forwarding to Sure's /mcp endpoint.
This supersedes the standalone compose in PR #1050.
* Fix compose --preset→--mode, add port 3000 trust comment, notification test
Review fixes:
- pipelock run uses --mode not --preset (would prevent stack startup)
- Document port 3000 exposes /mcp directly (auth still required)
- Add version requirement note for Pipelock MCP listener support
- Add test: tools/call sent as notification does not execute
* Add Pipelock agent security scan to CI
Scans PR diffs for leaked secrets and agent security risks.
Zero config, runs on every PR to main.
* Retrigger CI (v1 action tag now available)
* Harden checkout: persist-credentials false
Pipelock only reads local git history for diff scanning,
no auth token needed in .git/config.
* Chat improvements
* Delete/reset account via API for Flutter app
* Fix tests.
* Add "contact us" to settings
* Update mobile/lib/screens/chat_conversation_screen.dart
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
* Improve LLM special token detection
* Deactivated user shouldn't have API working
* Fix tests
* API-Key usage
* Flutter app launch failure on no network
* Handle deletion/reset delays
* Local cached data may become stale
* Use X-Api-Key correctly!
---------
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
The update action was calling set_current_balance (which triggers
sync_later internally) on every form submission, even when the balance
hadn't changed. This caused the account to enter a syncing state,
replacing the visible balance with a pulsing skeleton placeholder
until the sync completed.
Now we compare the submitted balance against the current value and
only call set_current_balance when it actually differs. Also removes
a redundant sync_later call that duplicated the one already inside
set_current_balance.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Sync Helm chart and Rails app versions in CI and release workflows
- values.yaml: default image.tag to "" so it uses Chart.appVersion
(was hardcoded to stale "0.6.6" while app was at 0.6.8-alpha.13)
- chart-ci.yml: add version-sync job that fails if version.rb,
Chart.yaml version, and Chart.yaml appVersion diverge; trigger on
version.rb changes too
- chart-release.yml: derive chart version from version.rb (single
source of truth) instead of auto-incrementing independent chart-v* tags
https://claude.ai/code/session_01Eq3WHBn3Uwjezxb6ctdjMB
* Default to `false` AI_DEBUG_MODE
* Apply suggestions from CodeRabbit
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
---------
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
When workflow_dispatch is triggered from a tag (e.g. v0.6.7) instead
of a branch, github.ref_name returns the tag name, causing filenames
like sure-v0.6.7-{stamp}.apk instead of sure-main-{stamp}.apk.
Guard against this by checking github.ref_type and falling back to the
repository's default branch when a tag is selected.
https://claude.ai/code/session_01TDfNkNxQ6uWxQxLAwJY5Qa
* Add workflow to build mobile apps from main without tagging
Adds a new `mobile-main-build.yml` workflow that can be triggered
manually via workflow_dispatch to build Android APK and iOS unsigned
builds from the main branch. Uses a `main-YYYYMMDDHHMI` stamp for
versioning (e.g. sure-main-202602181259.apk) and updates the gh-pages
README.md MOBILE_DOWNLOADS section with direct download links.
https://claude.ai/code/session_01TDfNkNxQ6uWxQxLAwJY5Qa
* Rename to mobile-build.yml and support any branch
Instead of hardcoding "main", derive the branch name from
github.ref_name, sanitise it for filenames/tags (slashes → hyphens),
and use it throughout: version, tag, release notes, and gh-pages
README. The checkout step now explicitly pins ref: ${{ github.ref }}
so the tag always matches the dispatched branch.
Example artifacts from main: sure-main-202602181259.apk
Example from feature/foo: sure-feature-foo-202602181259.apk
https://claude.ai/code/session_01TDfNkNxQ6uWxQxLAwJY5Qa
* Add continue-on-error to artifact download steps
If either the Android or iOS build fails, the download step would
hard-fail and abort the release job before the conditional logic in
"Prepare release assets" could handle the partial result. Adding
continue-on-error lets the workflow proceed so a release can still
be created with whichever artifacts succeeded.
https://claude.ai/code/session_01TDfNkNxQ6uWxQxLAwJY5Qa
* Fix in-place replacement of MOBILE_DOWNLOADS section in README
The previous logic stripped the marker block then appended the new
section at the end of the file, causing it to drift to the bottom on
every run. Now writes the section to a temp file and uses awk to
replace the block between the markers in-place, preserving the
section's original position in the README.
https://claude.ai/code/session_01TDfNkNxQ6uWxQxLAwJY5Qa
---------
Co-authored-by: Claude <noreply@anthropic.com>