mirror of
https://github.com/we-promise/sure
synced 2026-04-25 17:15:07 +02:00
More rebranding changes (#159)
* Replace Maybe for Sure in select code areas * Make sure passwords are consistent * Remove (admin|member) from demo data first name * Database and schema names finally to `sure` * Fix broken test * Another (benchmarking) database name to `sure_*` * More rebranding to Sure * Missed this Maybe mention in the same page * Random nitpicks and more Maybes * Demo data accounts and more Maybes * Test data account updates * Impersonation test accounts * Consistency with `compose.example.yml`
This commit is contained in:
@@ -74,8 +74,8 @@ rake demo_data:default
|
||||
|
||||
Visit http://localhost:3000 to view the app. You can log in with these demo credentials (from the DB seed):
|
||||
|
||||
- Email: `user@sure.local`
|
||||
- Password: `password`
|
||||
- Email: `user@example.com`
|
||||
- Password: `Password1!`
|
||||
|
||||
For further instructions, see guides below.
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ module SelfHostable
|
||||
if controller_name == "pages" && action_name == "redis_configuration_error"
|
||||
# If Redis is now working, redirect to home
|
||||
if redis_connected?
|
||||
redirect_to root_path, notice: "Redis is now configured properly! You can now setup your Maybe application."
|
||||
redirect_to root_path, notice: "Redis is now configured properly! You can now setup your Sure application."
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
@@ -30,7 +30,7 @@ class SubscriptionsController < ApplicationController
|
||||
def create
|
||||
if Current.family.can_start_trial?
|
||||
Current.family.start_trial_subscription!
|
||||
redirect_to root_path, notice: "Welcome to Maybe!"
|
||||
redirect_to root_path, notice: "Welcome to Sure!"
|
||||
else
|
||||
redirect_to root_path, alert: "You have already started or completed a trial. Please upgrade to continue."
|
||||
end
|
||||
@@ -51,7 +51,7 @@ class SubscriptionsController < ApplicationController
|
||||
|
||||
if checkout_result.success?
|
||||
Current.family.start_subscription!(checkout_result.subscription_id)
|
||||
redirect_to root_path, notice: "Welcome to Maybe! Your subscription has been created."
|
||||
redirect_to root_path, notice: "Welcome to Sure! Your subscription has been created."
|
||||
else
|
||||
redirect_to root_path, alert: "Something went wrong processing your subscription. Please contact us to get this fixed."
|
||||
end
|
||||
|
||||
@@ -80,7 +80,7 @@ class Account < ApplicationRecord
|
||||
balance = simplefin_account.current_balance || simplefin_account.available_balance || 0
|
||||
|
||||
# SimpleFin returns negative balances for credit cards (liabilities)
|
||||
# But Maybe expects positive balances for liabilities
|
||||
# But Sure expects positive balances for liabilities
|
||||
if account_type == "CreditCard" || account_type == "Loan"
|
||||
balance = balance.abs
|
||||
end
|
||||
|
||||
@@ -26,7 +26,7 @@ module Assistant::Configurable
|
||||
<<~PROMPT
|
||||
## Your identity
|
||||
|
||||
You are a friendly financial assistant for an open source personal finance application called "Maybe", which is short for "Maybe Finance".
|
||||
You are a friendly financial assistant for an open source personal finance application called "Sure", which is short for "Sure Finances".
|
||||
|
||||
## Your purpose
|
||||
|
||||
@@ -52,7 +52,7 @@ module Assistant::Configurable
|
||||
|
||||
#### User's preferred currency
|
||||
|
||||
Maybe is a multi-currency app where each user has a "preferred currency" setting.
|
||||
Sure is a multi-currency app where each user has a "preferred currency" setting.
|
||||
|
||||
When no currency is specified, use the user's preferred currency for formatting and displaying monetary values.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class Demo::Generator
|
||||
end
|
||||
|
||||
puts "👥 Creating empty family..."
|
||||
create_family_and_users!("Demo Family", "user@sure.local", onboarded: true, subscribed: true)
|
||||
create_family_and_users!("Demo Family", "user@example.com", onboarded: true, subscribed: true)
|
||||
|
||||
puts "✅ Empty demo data loaded successfully!"
|
||||
end
|
||||
@@ -53,14 +53,14 @@ class Demo::Generator
|
||||
end
|
||||
|
||||
puts "👥 Creating new user family..."
|
||||
create_family_and_users!("Demo Family", "user@sure.local", onboarded: false, subscribed: false)
|
||||
create_family_and_users!("Demo Family", "user@example.com", onboarded: false, subscribed: false)
|
||||
|
||||
puts "✅ New user demo data loaded successfully!"
|
||||
end
|
||||
end
|
||||
|
||||
# Generate comprehensive realistic demo data with multi-currency
|
||||
def generate_default_data!(skip_clear: false, email: "user@sure.local")
|
||||
def generate_default_data!(skip_clear: false, email: "user@example.com")
|
||||
if skip_clear
|
||||
puts "⏭️ Skipping data clearing (appending new family)..."
|
||||
else
|
||||
@@ -133,20 +133,20 @@ class Demo::Generator
|
||||
# Admin user
|
||||
family.users.create!(
|
||||
email: email,
|
||||
first_name: "Demo (admin)",
|
||||
last_name: "Maybe",
|
||||
first_name: "Jack",
|
||||
last_name: "Bogle",
|
||||
role: "admin",
|
||||
password: "password",
|
||||
password: "Password1!",
|
||||
onboarded_at: onboarded ? Time.current : nil
|
||||
)
|
||||
|
||||
# Member user
|
||||
family.users.create!(
|
||||
email: "partner_#{email}",
|
||||
first_name: "Demo (member)",
|
||||
last_name: "Maybe",
|
||||
first_name: "Eve",
|
||||
last_name: "Bogle",
|
||||
role: "member",
|
||||
password: "password",
|
||||
password: "Password1!",
|
||||
onboarded_at: onboarded ? Time.current : nil
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class FamilyExport < ApplicationRecord
|
||||
scope :ordered, -> { order(created_at: :desc) }
|
||||
|
||||
def filename
|
||||
"maybe_export_#{created_at.strftime('%Y%m%d_%H%M%S')}.zip"
|
||||
"sure_export_#{created_at.strftime('%Y%m%d_%H%M%S')}.zip"
|
||||
end
|
||||
|
||||
def downloadable?
|
||||
|
||||
@@ -37,12 +37,12 @@ class Import::Row < ApplicationRecord
|
||||
end
|
||||
|
||||
private
|
||||
# In the Maybe system, positive quantities == "inflows"
|
||||
# In the Sure system, positive quantities == "inflows"
|
||||
def apply_trade_signage_convention(value)
|
||||
value * (import.signage_convention == "inflows_positive" ? 1 : -1)
|
||||
end
|
||||
|
||||
# In the Maybe system, positive amounts == "outflows", so we must reverse signage
|
||||
# In the Sure system, positive amounts == "outflows", so we must reverse signage
|
||||
def apply_transaction_signage_convention(value)
|
||||
if import.amount_type_strategy == "signed_amount"
|
||||
value * (import.signage_convention == "inflows_positive" ? -1 : 1)
|
||||
|
||||
@@ -23,7 +23,7 @@ class MobileDevice < ApplicationRecord
|
||||
|
||||
app = Doorkeeper::Application.create!(
|
||||
name: "Mobile App - #{device_id}",
|
||||
redirect_uri: "maybe://oauth/callback", # Custom scheme for mobile
|
||||
redirect_uri: "sureapp://oauth/callback", # Custom scheme for mobile
|
||||
scopes: "read_write", # Use the configured scope
|
||||
confidential: false # Public client for mobile
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ class PlaidAccount::Investments::BalanceCalculator
|
||||
|
||||
# Plaid considers "brokerage cash" and "cash equivalent holdings" to all be part of "cash balance"
|
||||
#
|
||||
# Internally, we DO NOT. Maybe clearly distinguishes between "brokerage cash" vs. "holdings (i.e. invested cash)"
|
||||
# Internally, we DO NOT. Sure clearly distinguishes between "brokerage cash" vs. "holdings (i.e. invested cash)"
|
||||
# For this reason, we must manually calculate the cash balance based on "total value" and "holdings value"
|
||||
# See PlaidAccount::Investments::SecurityResolver for more details.
|
||||
def cash_balance
|
||||
|
||||
@@ -63,7 +63,7 @@ class PlaidAccount::Investments::SecurityResolver
|
||||
end
|
||||
end
|
||||
|
||||
# Plaid treats "brokerage cash" differently than us. Internally, Maybe treats "brokerage cash"
|
||||
# Plaid treats "brokerage cash" differently than us. Internally, Sure treats "brokerage cash"
|
||||
# as "uninvested cash" (i.e. cash that doesn't have a corresponding Security and can be withdrawn).
|
||||
#
|
||||
# Plaid treats everything as a "holding" with a corresponding Security. For example, "brokerage cash" (USD)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# categories we cannot directly assign Plaid categories as this would overwrite
|
||||
# user data and create a confusing experience.
|
||||
#
|
||||
# Automated category matching in the Maybe app has a hierarchy:
|
||||
# Automated category matching in the Sure app has a hierarchy:
|
||||
# 1. Naive string matching via CategoryAliasMatcher
|
||||
# 2. Rules-based matching set by user
|
||||
# 3. AI-powered matching (also enabled by user via rules)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class Provider::Plaid
|
||||
attr_reader :client, :region
|
||||
|
||||
MAYBE_SUPPORTED_PLAID_PRODUCTS = %w[transactions investments liabilities].freeze
|
||||
SUPPORTED_PLAID_PRODUCTS = %w[transactions investments liabilities].freeze
|
||||
MAX_HISTORY_DAYS = Rails.env.development? ? 90 : 730
|
||||
|
||||
def initialize(config, region: :us)
|
||||
@@ -45,7 +45,7 @@ class Provider::Plaid
|
||||
def get_link_token(user_id:, webhooks_url:, redirect_url:, accountable_type: nil, access_token: nil)
|
||||
request_params = {
|
||||
user: { client_user_id: user_id },
|
||||
client_name: "Maybe Finance",
|
||||
client_name: "Sure Finances",
|
||||
country_codes: country_codes,
|
||||
language: "en",
|
||||
webhook: webhooks_url,
|
||||
@@ -195,7 +195,7 @@ class Provider::Plaid
|
||||
def get_additional_consented_products(accountable_type)
|
||||
return [] if eu?
|
||||
|
||||
MAYBE_SUPPORTED_PLAID_PRODUCTS - [ get_primary_product(accountable_type) ]
|
||||
SUPPORTED_PLAID_PRODUCTS - [ get_primary_product(accountable_type) ]
|
||||
end
|
||||
|
||||
def eu?
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# There are hundreds of thousands of market securities that Maybe must handle.
|
||||
# There are hundreds of thousands of market securities that Sure must handle.
|
||||
# Due to the always-changing nature of the market, the health checker is responsible
|
||||
# for periodically checking active securities to ensure we can still fetch prices for them.
|
||||
#
|
||||
|
||||
@@ -79,8 +79,8 @@ class SimplefinAccount::Processor
|
||||
end
|
||||
|
||||
# SimpleFin uses banking convention (expenses negative, income positive)
|
||||
# Maybe expects opposite convention (expenses positive, income negative)
|
||||
# So we negate the amount to convert from SimpleFin to Maybe format
|
||||
# Sure expects opposite convention (expenses positive, income negative)
|
||||
# So we negate the amount to convert from SimpleFin to Sure format
|
||||
-parsed_amount
|
||||
rescue ArgumentError => e
|
||||
Rails.logger.error "Failed to parse SimpleFin transaction amount: #{amount_value.inspect} - #{e.message}"
|
||||
|
||||
@@ -193,7 +193,7 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def totp
|
||||
ROTP::TOTP.new(otp_secret, issuer: "Maybe Finance")
|
||||
ROTP::TOTP.new(otp_secret, issuer: "Sure Finances")
|
||||
end
|
||||
|
||||
def verify_backup_code?(code)
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<%= render "chats/ai_avatar" %>
|
||||
</div>
|
||||
|
||||
<h3 class="text-sm font-medium text-primary mb-1 -mt-2 text-center">Enable Maybe AI</h3>
|
||||
<h3 class="text-sm font-medium text-primary mb-1 -mt-2 text-center">Enable AI Chats</h3>
|
||||
|
||||
<p class="text-gray-600 mb-4 text-sm text-center">
|
||||
<% if Current.user.ai_available? %>
|
||||
Maybe AI can answer financial questions and provide insights based on your data. To use this feature you'll need to explicitly enable it.
|
||||
AI chat can answer financial questions and provide insights based on your data. To use this feature you'll need to explicitly enable it.
|
||||
<% else %>
|
||||
To use the AI assistant, you need to set the <code class="bg-surface-inset px-1 py-0.5 rounded font-mono text-xs">OPENAI_ACCESS_TOKEN</code>
|
||||
environment variable or configure it in the Self-Hosting settings of your instance.
|
||||
@@ -18,7 +18,7 @@
|
||||
<%= form_with url: user_path(Current.user), method: :patch, class: "w-full", data: { turbo: false } do |form| %>
|
||||
<%= form.hidden_field "user[ai_enabled]", value: true %>
|
||||
<%= form.hidden_field "user[redirect_to]", value: "home" %>
|
||||
<%= form.submit "Enable Maybe AI", class: "cursor-pointer hover:bg-inverse-hover w-full py-2 px-4 bg-inverse fg-inverse rounded-lg text-sm font-medium" %>
|
||||
<%= form.submit "Enable AI Chats", class: "cursor-pointer hover:bg-inverse-hover w-full py-2 px-4 bg-inverse fg-inverse rounded-lg text-sm font-medium" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<%= render "chats/ai_avatar" %>
|
||||
|
||||
<div class="max-w-[85%] text-sm space-y-4 text-primary">
|
||||
<p>Hey <%= Current.user&.first_name || "there" %>! I'm an AI built by Maybe to help with your finances. I have access to the web and your account data.</p>
|
||||
<p>Hey <%= Current.user&.first_name || "there" %>! I'm an AI/large-language-model that can help with your finances. I have access to the web and your account data.</p>
|
||||
|
||||
<p>
|
||||
You can use <span class="bg-container border border-secondary px-1.5 py-0.5 rounded font-mono text-xs">/</span> to access commands
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<div class="bg-amber-50 border border-amber-200 rounded-lg p-3">
|
||||
<p class="text-sm text-amber-800">
|
||||
<strong>Note:</strong> This export includes all of your data, but only some of the data can be imported back into Maybe via the CSV import feature. We support account, transaction (with category and tags), and trade imports. Other account data cannot be imported and is for your records only.
|
||||
<strong>Note:</strong> This export includes all of your data, but only some of the data can be imported back via the CSV import feature. We support account, transaction (with category and tags), and trade imports. Other account data cannot be imported and is for your records only.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
</div>
|
||||
<div class="flex items-center space-x-2 px-2 py-2 text-white gap-4">
|
||||
<% if pending_session.present? %>
|
||||
<p class="text-xs max-w-3xl text-right">Maybe support staff has requested access to your account (likely to help you with a support request). If you approve the request, all activity they take will be logged for security and audit purposes.</p>
|
||||
<p class="text-xs max-w-3xl text-right">Sure support staff has requested access to your account (likely to help you with a support request). If you approve the request, all activity they take will be logged for security and audit purposes.</p>
|
||||
<%= button_to "Approve", approve_impersonation_session_path(pending_session), method: :put, class: "inline-flex items-center px-3 py-1.5 border border-transparent text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-green-500" %>
|
||||
<%= button_to "Reject", reject_impersonation_session_path(pending_session), method: :put, class: "inline-flex items-center px-3 py-1.5 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-red-500" %>
|
||||
<% elsif in_progress_session.present? %>
|
||||
<p class="text-xs max-w-3xl text-right">Someone from the Maybe Finance team is currently viewing your data. You may end the session at any time.</p>
|
||||
<p class="text-xs max-w-3xl text-right">Someone from the Sure Finances team is currently viewing your data. You may end the session at any time.</p>
|
||||
<%= button_to "End Session", complete_impersonation_session_path(in_progress_session), method: :put, class: "inline-flex items-center px-3 py-1.5 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" %>
|
||||
<% else %>
|
||||
<p class="text-xs max-w-3xl text-right text-red-500">Something went wrong. Please contact us.</p>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<% unless Security.provider %>
|
||||
<div class="alert alert-warning">
|
||||
<p>
|
||||
<strong>Note:</strong> The security prices provider is not configured. Your trade imports will work, but Maybe will not backfill price history. Please go to your settings to configure this.
|
||||
<strong>Note:</strong> The security prices provider is not configured. Your trade imports will work, but Sure will not backfill price history. Please go to your settings to configure this.
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<h2 class="text-3xl font-medium text-primary text-center">
|
||||
Maybe Authorization
|
||||
Sure Authorization
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<div class="grow max-w-lg w-full mx-auto bg-surface flex flex-col justify-center md:py-0 py-6 px-4 md:px-0">
|
||||
<div>
|
||||
<div class="space-y-1 mb-6 text-center">
|
||||
<h1 class="text-2xl font-medium md:text-2xl">What brings you to Maybe?</h1>
|
||||
<p class="text-secondary text-sm">Select one or more goals that you have with using Maybe as your personal finance tool.</p>
|
||||
<h1 class="text-2xl font-medium md:text-2xl">What brings you to Sure?</h1>
|
||||
<p class="text-secondary text-sm">Select one or more goals that you have with using Sure as your personal finance tool.</p>
|
||||
</div>
|
||||
|
||||
<%= form_with model: @user do |form| %>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<%= image_tag "logo-color.png", class: "w-16 mb-6" %>
|
||||
|
||||
<p class="text-xl lg:text-3xl text-primary font-display font-medium">
|
||||
Try Maybe for 14 days.
|
||||
Try Sure for 14 days.
|
||||
</p>
|
||||
|
||||
<h2 class="text-xl lg:text-3xl font-display text-secondary font-medium mb-2">
|
||||
@@ -25,13 +25,13 @@
|
||||
</h2>
|
||||
|
||||
<p class="text-sm text-secondary text-center mb-8">
|
||||
Starting the trial activates your account for Maybe. You won't need to enter payment details.
|
||||
Starting the trial activates your account for Sure. You won't need to enter payment details.
|
||||
</p>
|
||||
|
||||
<div class="w-full">
|
||||
<% if Current.family.can_start_trial? %>
|
||||
<%= render DS::Button.new(
|
||||
text: "Try Maybe for 14 days",
|
||||
text: "Try Sure for 14 days",
|
||||
href: subscription_path,
|
||||
full_width: true,
|
||||
data: { turbo: false }
|
||||
@@ -65,7 +65,7 @@
|
||||
<div class="space-y-12">
|
||||
<div class="space-y-1.5 text-sm">
|
||||
<p class="text-primary font-medium">Today</p>
|
||||
<p class="text-secondary">You'll get free access to Maybe for 14 days</p>
|
||||
<p class="text-secondary">You'll get free access to Sure for 14 days</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-1.5 text-sm">
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
<div class="space-y-1.5 text-sm">
|
||||
<p class="text-primary font-medium">In 14 days (<%= 14.days.from_now.strftime("%B %d") %>)</p>
|
||||
<p class="text-secondary">Your trial ends — subscribe to continue using Maybe</p>
|
||||
<p class="text-secondary">Your trial ends — subscribe to continue using Sure</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
<div class="flex flex-col gap-4 items-center">
|
||||
<%= render "chats/ai_avatar" %>
|
||||
<p class="text-sm text-primary text-center">Unlimited access and chats with Maybe AI</p>
|
||||
<p class="text-sm text-primary text-center">Unlimited access and chats with Sure AI</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-4 items-center">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<% content_for :title, "Redis Configuration Required - Maybe" %>
|
||||
<% content_for :title, "Redis Configuration Required - Sure" %>
|
||||
|
||||
<div class="flex items-center justify-center h-full p-4 sm:p-6 lg:p-8">
|
||||
<div class="w-full max-w-md sm:max-w-lg lg:max-w-2xl">
|
||||
@@ -9,7 +9,7 @@
|
||||
<%= icon "alert-triangle", class: "w-8 h-8 text-red-600" %>
|
||||
</div>
|
||||
<h1 class="text-xl sm:text-2xl font-bold text-primary mb-2">Redis Configuration Required</h1>
|
||||
<p class="text-sm sm:text-base text-muted">Your self-hosted Maybe installation needs Redis to be properly configured.</p>
|
||||
<p class="text-sm sm:text-base text-muted">Your self-hosted Sure installation needs Redis to be properly configured.</p>
|
||||
</div>
|
||||
|
||||
<!-- Explanation -->
|
||||
@@ -19,7 +19,7 @@
|
||||
<%= icon "info", class: "w-5 h-5 text-amber-600 mt-0.5 mr-3 flex-shrink-0" %>
|
||||
<div class="text-sm text-amber-800">
|
||||
<p><strong>Why is Redis required?</strong></p>
|
||||
<p class="mt-1">Maybe uses Redis to power Sidekiq background jobs for tasks like syncing account data, processing imports, and other background operations that keep your financial data up to date.</p>
|
||||
<p class="mt-1">Sure uses Redis to power Sidekiq background jobs for tasks like syncing account data, processing imports, and other background operations that keep your financial data up to date.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,7 +28,7 @@
|
||||
<div class="text-center space-y-4">
|
||||
<%= render DS::Link.new(
|
||||
text: "View Setup Guide",
|
||||
href: "https://github.com/maybe-finance/maybe/blob/main/docs/hosting/docker.md",
|
||||
href: "https://github.com/we-promise/sure/blob/main/docs/hosting/docker.md",
|
||||
variant: "primary",
|
||||
size: "lg",
|
||||
icon: "external-link",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<%= content_for :page_title, "Create New API Key" %>
|
||||
|
||||
<%= settings_section title: nil, subtitle: "Generate a new API key to access your Maybe data programmatically." do %>
|
||||
<%= settings_section title: nil, subtitle: "Generate a new API key to access your Sure data programmatically." do %>
|
||||
<%= styled_form_with model: @api_key, url: settings_api_key_path, class: "space-y-4" do |form| %>
|
||||
<%= form.text_field :name,
|
||||
placeholder: "e.g., My Budget App, Portfolio Tracker",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
{ label: t(".country") },
|
||||
{ data: { auto_submit_form_target: "auto" } } %>
|
||||
|
||||
<p class="text-xs italic pl-2 text-secondary">Please note, we are still working on translations for various languages. Please see the <%= link_to "I18n issue", "https://github.com/maybe-finance/maybe/issues/1225", target: "_blank", class: "underline" %> for more information.</p>
|
||||
<p class="text-xs italic pl-2 text-secondary">Please note, we are still working on translations for various languages.</p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<div class="flex items-center py-0.5 px-0.5 gap-1 fixed right-1 top-1 shadow-xs border border-alpha-black-50 rounded-md bg-container">
|
||||
<p class="text-xs text-secondary pl-2">Version: <%= Maybe.version.to_release_tag %></p>
|
||||
<p class="text-xs text-secondary pl-2">Version: <%= Sure.version.to_release_tag %></p>
|
||||
</div>
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
|
||||
<h2 class="text-xl lg:text-3xl font-display font-medium mb-2">
|
||||
<span class="text-secondary">Unlock</span>
|
||||
<span class="bg-gradient-to-r from-[#EABE7F] to-[#957049] bg-clip-text text-transparent">Maybe</span>
|
||||
<span class="bg-gradient-to-r from-[#EABE7F] to-[#957049] bg-clip-text text-transparent">Sure</span>
|
||||
<span class="text-secondary">today</span>
|
||||
</h2>
|
||||
|
||||
<p class="text-sm text-secondary mb-8">To continue using Maybe pick a plan below.</p>
|
||||
<p class="text-sm text-secondary mb-8">To continue using Sure pick a plan below.</p>
|
||||
|
||||
<%= form_with url: new_subscription_path, method: :get, class: "max-w-xs", data: { turbo: false } do |form| %>
|
||||
<div class="space-y-4 mb-6">
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
<div class="text-center space-y-2">
|
||||
<%= render DS::Button.new(
|
||||
text: "Subscribe and unlock Maybe",
|
||||
text: "Subscribe and unlock Sure",
|
||||
variant: "primary",
|
||||
full_width: true
|
||||
) %>
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
<div class="px-4 py-3 border-t border-tertiary">
|
||||
<p class="text-sm">
|
||||
<span class="font-medium text-primary">Version:</span>
|
||||
<%= link_to Maybe.version.to_release_tag, "https://github.com/we-promise/sure/releases/tag/#{Maybe.version.to_release_tag}", target: "_blank", class: "hover:underline" %>
|
||||
<%= link_to Sure.version.to_release_tag, "https://github.com/we-promise/sure/releases/tag/#{Sure.version.to_release_tag}", target: "_blank", class: "hover:underline" %>
|
||||
|
||||
<% if Maybe.commit_sha.present? %>
|
||||
(<%= link_to Maybe.commit_sha.first(7), "https://github.com/we-promise/sure/commit/#{Maybe.commit_sha}", target: "_blank", class: "hover:underline" %>)
|
||||
<% if Sure.commit_sha.present? %>
|
||||
(<%= link_to Sure.commit_sha.first(7), "https://github.com/we-promise/sure/commit/#{Sure.commit_sha}", target: "_blank", class: "hover:underline" %>)
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
#
|
||||
|
||||
x-db-env: &db_env
|
||||
POSTGRES_USER: ${POSTGRES_USER:-maybe_user}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-maybe_password}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-maybe_production}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-sure_user}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-sure_password}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-sure_production}
|
||||
|
||||
x-rails-env: &rails_env
|
||||
<<: *db_env
|
||||
|
||||
@@ -6,7 +6,7 @@ require "rails/all"
|
||||
# you've limited to :test, :development, or :production.
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
module Maybe
|
||||
module Sure
|
||||
class Application < Rails::Application
|
||||
# Initialize configuration defaults for originally generated Rails version.
|
||||
config.load_defaults 7.2
|
||||
|
||||
@@ -7,4 +7,4 @@ test:
|
||||
production:
|
||||
adapter: redis
|
||||
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
|
||||
channel_prefix: maybe_production
|
||||
channel_prefix: sure_production
|
||||
|
||||
@@ -9,12 +9,12 @@ default: &default
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
database: <%= ENV.fetch("POSTGRES_DB") { "maybe_development" } %>
|
||||
database: <%= ENV.fetch("POSTGRES_DB") { "sure_development" } %>
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
database: <%= ENV.fetch("POSTGRES_DB") { "maybe_test" } %>
|
||||
database: <%= ENV.fetch("POSTGRES_DB") { "sure_test" } %>
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
database: <%= ENV.fetch("POSTGRES_DB") { "maybe_production" } %>
|
||||
database: <%= ENV.fetch("POSTGRES_DB") { "sure_production" } %>
|
||||
|
||||
@@ -24,7 +24,7 @@ Rails.application.configure do
|
||||
}
|
||||
|
||||
# Set default sender email for tests
|
||||
ENV["EMAIL_SENDER"] = "hello@maybefinance.com"
|
||||
ENV["EMAIL_SENDER"] = "hello@example.com"
|
||||
|
||||
# Show full error reports and disable caching.
|
||||
config.consider_all_requests_local = true
|
||||
|
||||
@@ -2,8 +2,8 @@ require "sidekiq/web"
|
||||
|
||||
if Rails.env.production?
|
||||
Sidekiq::Web.use(Rack::Auth::Basic) do |username, password|
|
||||
configured_username = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_USERNAME", "maybe"))
|
||||
configured_password = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_PASSWORD", "maybe"))
|
||||
configured_username = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_USERNAME", "sure"))
|
||||
configured_password = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_PASSWORD", "sure"))
|
||||
|
||||
ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(username), configured_username) &&
|
||||
ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(password), configured_password)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module Maybe
|
||||
module Sure
|
||||
class << self
|
||||
def version
|
||||
Semver.new(semver)
|
||||
|
||||
@@ -280,8 +280,8 @@ Rails.application.routes.draw do
|
||||
|
||||
get "imports/:import_id/upload/sample_csv", to: "import/uploads#sample_csv", as: :import_upload_sample_csv
|
||||
|
||||
get "privacy", to: redirect("https://maybefinance.com/privacy")
|
||||
get "terms", to: redirect("https://maybefinance.com/tos")
|
||||
get "privacy", to: redirect("about:blank")
|
||||
get "terms", to: redirect("about:blank")
|
||||
|
||||
# Defines the root path route ("/")
|
||||
root "pages#dashboard"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Create OAuth applications for Maybe's first-party apps
|
||||
# Create OAuth applications for Sure's first-party apps
|
||||
# These are the only OAuth apps that will exist - external developers use API keys
|
||||
|
||||
# Maybe iOS App
|
||||
ios_app = Doorkeeper::Application.find_or_create_by(name: "Maybe iOS") do |app|
|
||||
app.redirect_uri = "maybe://oauth/callback"
|
||||
# Sure iOS App
|
||||
ios_app = Doorkeeper::Application.find_or_create_by(name: "Sure iOS") do |app|
|
||||
app.redirect_uri = "sureapp://oauth/callback"
|
||||
app.scopes = "read_accounts read_transactions read_balances"
|
||||
app.confidential = false # Public client (mobile app)
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Chat API Documentation
|
||||
|
||||
The Chat API allows external applications to interact with Maybe's AI chat functionality.
|
||||
The Chat API allows external applications to interact with Sure's AI chat functionality.
|
||||
|
||||
## Authentication
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ After doing this, make sure and restart the app:
|
||||
```bash
|
||||
docker compose pull # This pulls the "latest" published image from GHCR
|
||||
docker compose build # This rebuilds the app with updates
|
||||
docker compose up --no-deps -d app # This restarts the app using the newest version
|
||||
docker compose up --no-deps -d web worker # This restarts the app using the newest version
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
@@ -189,5 +189,5 @@ By running the commands below, you will delete your existing Sure database and "
|
||||
docker compose down
|
||||
docker volume rm sure_postgres-data # this is the name of the volume the DB is mounted to
|
||||
docker compose up
|
||||
docker exec -it sure-postgres-1 psql -U maybe -d maybe_production -c "SELECT 1;" # This will verify that the issue is fixed
|
||||
docker exec -it sure-db-1 psql -U sure_user -d sure_production -c "SELECT 1;" # This will verify that the issue is fixed
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Benchmarking requires a production-like data sample, so requires some up-front setup.
|
||||
#
|
||||
# 1. Load a scrubbed production-like slice of data into maybe_benchmarking DB locally
|
||||
# 2. Setup .env.production so that the Rails app can boot with RAILS_ENV=production and connect to local maybe_benchmarking DB
|
||||
# 1. Load a scrubbed production-like slice of data into sure_benchmarking DB locally
|
||||
# 2. Setup .env.production so that the Rails app can boot with RAILS_ENV=production and connect to local sure_benchmarking DB
|
||||
# 3. Run `rake benchmark_dump:06_setup_bench_user`
|
||||
# 4. Run locally, find endpoint needed
|
||||
# 5. Run an endpoint, example: `ENDPOINT=/budgets/jun-2025/budget_categories/245637cb-129f-4612-b0a8-1de57559372b RAILS_ENV=production BENCHMARKING_ENABLED=true RAILS_LOG_LEVEL=debug rake benchmarking:ips`
|
||||
@@ -11,7 +11,7 @@ namespace :benchmarking do
|
||||
Benchmark.ips do |x|
|
||||
x.config(time: 30, warmup: 10)
|
||||
|
||||
family = User.find_by(email: "user@sure.local").family
|
||||
family = User.find_by(email: "user@example.com").family
|
||||
scope = family.transactions.active
|
||||
|
||||
# x.report("IncomeStatement::Totals") do
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace :data_migration do
|
||||
eu_items.find_each do |item|
|
||||
request = Plaid::ItemWebhookUpdateRequest.new(
|
||||
access_token: item.access_token,
|
||||
webhook: "https://app.maybefinance.com/webhooks/plaid_eu"
|
||||
webhook: "https://app.sure.am/webhooks/plaid_eu"
|
||||
)
|
||||
|
||||
provider.client.item_webhook_update(request)
|
||||
|
||||
@@ -14,7 +14,7 @@ class CustomAuth < DerailedBenchmarks::AuthHelper
|
||||
|
||||
def call(env)
|
||||
# Make sure this user is created in the DB with realistic data before running benchmarks
|
||||
user = User.find_by!(email: "user@sure.local")
|
||||
user = User.find_by!(email: "user@example.com")
|
||||
|
||||
Rails.logger.debug "Found user for benchmarking: #{user.email}"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ class DialogComponentPreview < ViewComponent::Preview
|
||||
dialog.with_header(title: "Sample modal title")
|
||||
|
||||
dialog.with_body do
|
||||
"Welcome to Maybe! This is some test modal content."
|
||||
"Welcome to Sure! This is some test modal content."
|
||||
end
|
||||
|
||||
dialog.with_action(cancel_action: true, text: "Cancel", variant: "outline")
|
||||
|
||||
@@ -2,7 +2,7 @@ require "test_helper"
|
||||
|
||||
class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
test "impersonation session logs all activity for auditing" do
|
||||
sign_in impersonator = users(:maybe_support_staff)
|
||||
sign_in impersonator = users(:sure_support_staff)
|
||||
impersonated = users(:family_member)
|
||||
|
||||
impersonator_session = impersonation_sessions(:in_progress)
|
||||
@@ -16,7 +16,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
test "super admin can request an impersonation session" do
|
||||
sign_in users(:maybe_support_staff)
|
||||
sign_in users(:sure_support_staff)
|
||||
|
||||
post impersonation_sessions_path, params: { impersonation_session: { impersonated_id: users(:family_member).id } }
|
||||
|
||||
@@ -25,7 +25,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
test "super admin can join and leave an in progress impersonation session" do
|
||||
sign_in super_admin = users(:maybe_support_staff)
|
||||
sign_in super_admin = users(:sure_support_staff)
|
||||
|
||||
impersonator_session = impersonation_sessions(:in_progress)
|
||||
|
||||
@@ -52,7 +52,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
test "super admin can complete an impersonation session" do
|
||||
sign_in super_admin = users(:maybe_support_staff)
|
||||
sign_in super_admin = users(:sure_support_staff)
|
||||
|
||||
impersonator_session = impersonation_sessions(:in_progress)
|
||||
|
||||
@@ -77,7 +77,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
test "super admin cannot accept an impersonation session" do
|
||||
sign_in super_admin = users(:maybe_support_staff)
|
||||
sign_in super_admin = users(:sure_support_staff)
|
||||
|
||||
impersonator_session = impersonation_sessions(:in_progress)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class MfaControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
test "enables MFA with valid code" do
|
||||
@user.setup_mfa!
|
||||
totp = ROTP::TOTP.new(@user.otp_secret, issuer: "Maybe")
|
||||
totp = ROTP::TOTP.new(@user.otp_secret, issuer: "Sure Finances")
|
||||
|
||||
post mfa_path, params: { code: totp.now }
|
||||
|
||||
@@ -70,7 +70,7 @@ class MfaControllerTest < ActionDispatch::IntegrationTest
|
||||
sign_out
|
||||
|
||||
post sessions_path, params: { email: @user.email, password: user_password_test }
|
||||
totp = ROTP::TOTP.new(@user.otp_secret, issuer: "Maybe")
|
||||
totp = ROTP::TOTP.new(@user.otp_secret, issuer: "Sure Finances")
|
||||
|
||||
post verify_mfa_path, params: { code: totp.now }
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class OnboardingsControllerTest < ActionDispatch::IntegrationTest
|
||||
test "should get goals" do
|
||||
get goals_onboarding_url
|
||||
assert_response :success
|
||||
assert_select "h1", text: /What brings you to Maybe/i
|
||||
assert_select "h1", text: /What brings you to Sure/i
|
||||
end
|
||||
|
||||
test "should get trial" do
|
||||
|
||||
@@ -26,7 +26,7 @@ class SubscriptionsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
assert_redirected_to root_path
|
||||
assert_equal "Welcome to Maybe!", flash[:notice]
|
||||
assert_equal "Welcome to Sure!", flash[:notice]
|
||||
assert_equal "trialing", @family.subscription.status
|
||||
assert_in_delta Subscription::TRIAL_DAYS.days.from_now, @family.subscription.trial_ends_at, 1.minute
|
||||
end
|
||||
@@ -71,6 +71,6 @@ class SubscriptionsControllerTest < ActionDispatch::IntegrationTest
|
||||
get success_subscription_url(session_id: "test-session-id")
|
||||
|
||||
assert @family.subscription.active?
|
||||
assert_equal "Welcome to Maybe! Your subscription has been created.", flash[:notice]
|
||||
assert_equal "Welcome to Sure! Your subscription has been created.", flash[:notice]
|
||||
end
|
||||
end
|
||||
|
||||
2
test/fixtures/impersonation_sessions.yml
vendored
2
test/fixtures/impersonation_sessions.yml
vendored
@@ -1,4 +1,4 @@
|
||||
in_progress:
|
||||
impersonator: maybe_support_staff
|
||||
impersonator: sure_support_staff
|
||||
impersonated: family_member
|
||||
status: in_progress
|
||||
|
||||
6
test/fixtures/users.yml
vendored
6
test/fixtures/users.yml
vendored
@@ -2,17 +2,17 @@ empty:
|
||||
family: empty
|
||||
first_name: User
|
||||
last_name: One
|
||||
email: user1@email.com
|
||||
email: user1@example.com
|
||||
password_digest: $2a$12$XoNBo/cMCyzpYtvhrPAhsubG21mELX48RAcjSVCRctW8dG8wrDIla
|
||||
onboarded_at: <%= 3.days.ago %>
|
||||
role: admin
|
||||
ai_enabled: true
|
||||
|
||||
maybe_support_staff:
|
||||
sure_support_staff:
|
||||
family: empty
|
||||
first_name: Support
|
||||
last_name: Admin
|
||||
email: support@maybefinance.com
|
||||
email: support@sure.am
|
||||
password_digest: $2a$12$XoNBo/cMCyzpYtvhrPAhsubG21mELX48RAcjSVCRctW8dG8wrDIla
|
||||
role: super_admin
|
||||
onboarded_at: <%= 3.days.ago %>
|
||||
|
||||
@@ -8,7 +8,7 @@ class OauthMobileTest < ActionDispatch::IntegrationTest
|
||||
sign_in(@user)
|
||||
|
||||
@oauth_app = Doorkeeper::Application.create!(
|
||||
name: "Maybe Mobile App",
|
||||
name: "Sure Mobile App",
|
||||
redirect_uri: "sureapp://oauth/callback",
|
||||
scopes: "read"
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ class EmailConfirmationMailerTest < ActionMailer::TestCase
|
||||
mail = EmailConfirmationMailer.with(user: user).confirmation_email
|
||||
assert_equal I18n.t("email_confirmation_mailer.confirmation_email.subject"), mail.subject
|
||||
assert_equal [ user.unconfirmed_email ], mail.to
|
||||
assert_equal [ "hello@maybefinance.com" ], mail.from
|
||||
assert_equal [ "hello@example.com" ], mail.from
|
||||
assert_match "confirm", mail.body.encoded
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,7 +29,7 @@ class FamilyExportTest < ActiveSupport::TestCase
|
||||
test "filename is generated correctly" do
|
||||
travel_to Time.zone.local(2024, 1, 15, 14, 30, 0) do
|
||||
export = @family.family_exports.create!
|
||||
expected_filename = "maybe_export_20240115_143000.zip"
|
||||
expected_filename = "sure_export_20240115_143000.zip"
|
||||
assert_equal expected_filename, export.filename
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,13 +9,13 @@ class ImpersonationSessionTest < ActiveSupport::TestCase
|
||||
assert_raises(ActiveRecord::RecordInvalid) do
|
||||
ImpersonationSession.create!(
|
||||
impersonator: regular_user,
|
||||
impersonated: users(:maybe_support_staff)
|
||||
impersonated: users(:sure_support_staff)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "super admin cannot be impersonated" do
|
||||
super_admin = users(:maybe_support_staff)
|
||||
super_admin = users(:sure_support_staff)
|
||||
|
||||
assert super_admin.super_admin?
|
||||
|
||||
@@ -28,7 +28,7 @@ class ImpersonationSessionTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test "impersonation session must have different impersonator and impersonated" do
|
||||
super_admin = users(:maybe_support_staff)
|
||||
super_admin = users(:sure_support_staff)
|
||||
|
||||
assert_raises(ActiveRecord::RecordInvalid) do
|
||||
ImpersonationSession.create!(
|
||||
|
||||
@@ -106,7 +106,7 @@ class UserTest < ActiveSupport::TestCase
|
||||
user = users(:family_member)
|
||||
user.setup_mfa!
|
||||
|
||||
totp = ROTP::TOTP.new(user.otp_secret, issuer: "Maybe")
|
||||
totp = ROTP::TOTP.new(user.otp_secret, issuer: "Sure Finances")
|
||||
valid_code = totp.now
|
||||
|
||||
assert user.verify_otp?(valid_code)
|
||||
@@ -136,7 +136,7 @@ class UserTest < ActiveSupport::TestCase
|
||||
|
||||
assert_match %r{otpauth://totp/}, user.provisioning_uri
|
||||
assert_match %r{secret=#{user.otp_secret}}, user.provisioning_uri
|
||||
assert_match %r{issuer=Maybe}, user.provisioning_uri
|
||||
assert_match %r{issuer=Sure}, user.provisioning_uri
|
||||
end
|
||||
|
||||
test "ai_available? returns true when openai access token set in settings" do
|
||||
|
||||
@@ -12,7 +12,7 @@ class ChatsTest < ApplicationSystemTestCase
|
||||
visit root_path
|
||||
|
||||
within "#chat-container" do
|
||||
assert_selector "h3", text: "Enable Maybe AI"
|
||||
assert_selector "h3", text: "Enable AI Chats"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class OnboardingsTest < ApplicationSystemTestCase
|
||||
|
||||
# Should redirect to goals page
|
||||
assert_current_path goals_onboarding_path
|
||||
assert_text "What brings you to Maybe?"
|
||||
assert_text "What brings you to Sure?"
|
||||
end
|
||||
|
||||
test "preferences page renders chart without errors" do
|
||||
@@ -137,7 +137,7 @@ class OnboardingsTest < ApplicationSystemTestCase
|
||||
|
||||
visit goals_onboarding_path
|
||||
|
||||
assert_text "What brings you to Maybe?"
|
||||
assert_text "What brings you to Sure?"
|
||||
assert_button "Next"
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ http_interactions:
|
||||
uri: https://sandbox.plaid.com/link/token/create
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"client_name":"Maybe Finance","language":"en","country_codes":["US","CA"],"user":{"client_user_id":"test-user-id"},"products":["transactions"],"additional_consented_products":["investments","liabilities"],"webhook":"https://example.com/webhooks","redirect_uri":"http://localhost:3000/accounts","transactions":{"days_requested":730}}'
|
||||
string: '{"client_name":"Sure Finances","language":"en","country_codes":["US","CA"],"user":{"client_user_id":"test-user-id"},"products":["transactions"],"additional_consented_products":["investments","liabilities"],"webhook":"https://example.com/webhooks","redirect_uri":"http://localhost:3000/accounts","transactions":{"days_requested":730}}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json
|
||||
|
||||
@@ -114,13 +114,13 @@ http_interactions:
|
||||
"postal_code": "12345",
|
||||
"state": null
|
||||
},
|
||||
"email": "user@sure.local",
|
||||
"email": "user@example.com",
|
||||
"name": "Test Checkout User",
|
||||
"phone": null,
|
||||
"tax_exempt": "none",
|
||||
"tax_ids": []
|
||||
},
|
||||
"customer_email": "user@sure.local",
|
||||
"customer_email": "user@example.com",
|
||||
"discounts": [],
|
||||
"expires_at": 1746368350,
|
||||
"invoice": "in_1RKguoQT2jbOS8G0PuBVklxw",
|
||||
|
||||
Reference in New Issue
Block a user