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:
Juan José Mata
2025-09-24 00:19:51 +02:00
committed by GitHub
parent 7245dd79a2
commit 5706280dd7
60 changed files with 116 additions and 116 deletions

View File

@@ -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): Visit http://localhost:3000 to view the app. You can log in with these demo credentials (from the DB seed):
- Email: `user@sure.local` - Email: `user@example.com`
- Password: `password` - Password: `Password1!`
For further instructions, see guides below. For further instructions, see guides below.

View File

@@ -23,7 +23,7 @@ module SelfHostable
if controller_name == "pages" && action_name == "redis_configuration_error" if controller_name == "pages" && action_name == "redis_configuration_error"
# If Redis is now working, redirect to home # If Redis is now working, redirect to home
if redis_connected? 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 end
return return

View File

@@ -30,7 +30,7 @@ class SubscriptionsController < ApplicationController
def create def create
if Current.family.can_start_trial? if Current.family.can_start_trial?
Current.family.start_trial_subscription! Current.family.start_trial_subscription!
redirect_to root_path, notice: "Welcome to Maybe!" redirect_to root_path, notice: "Welcome to Sure!"
else else
redirect_to root_path, alert: "You have already started or completed a trial. Please upgrade to continue." redirect_to root_path, alert: "You have already started or completed a trial. Please upgrade to continue."
end end
@@ -51,7 +51,7 @@ class SubscriptionsController < ApplicationController
if checkout_result.success? if checkout_result.success?
Current.family.start_subscription!(checkout_result.subscription_id) 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 else
redirect_to root_path, alert: "Something went wrong processing your subscription. Please contact us to get this fixed." redirect_to root_path, alert: "Something went wrong processing your subscription. Please contact us to get this fixed."
end end

View File

@@ -80,7 +80,7 @@ class Account < ApplicationRecord
balance = simplefin_account.current_balance || simplefin_account.available_balance || 0 balance = simplefin_account.current_balance || simplefin_account.available_balance || 0
# SimpleFin returns negative balances for credit cards (liabilities) # 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" if account_type == "CreditCard" || account_type == "Loan"
balance = balance.abs balance = balance.abs
end end

View File

@@ -26,7 +26,7 @@ module Assistant::Configurable
<<~PROMPT <<~PROMPT
## Your identity ## 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 ## Your purpose
@@ -52,7 +52,7 @@ module Assistant::Configurable
#### User's preferred currency #### 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. When no currency is specified, use the user's preferred currency for formatting and displaying monetary values.

View File

@@ -38,7 +38,7 @@ class Demo::Generator
end end
puts "👥 Creating empty family..." 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!" puts "✅ Empty demo data loaded successfully!"
end end
@@ -53,14 +53,14 @@ class Demo::Generator
end end
puts "👥 Creating new user family..." 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!" puts "✅ New user demo data loaded successfully!"
end end
end end
# Generate comprehensive realistic demo data with multi-currency # 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 if skip_clear
puts "⏭️ Skipping data clearing (appending new family)..." puts "⏭️ Skipping data clearing (appending new family)..."
else else
@@ -133,20 +133,20 @@ class Demo::Generator
# Admin user # Admin user
family.users.create!( family.users.create!(
email: email, email: email,
first_name: "Demo (admin)", first_name: "Jack",
last_name: "Maybe", last_name: "Bogle",
role: "admin", role: "admin",
password: "password", password: "Password1!",
onboarded_at: onboarded ? Time.current : nil onboarded_at: onboarded ? Time.current : nil
) )
# Member user # Member user
family.users.create!( family.users.create!(
email: "partner_#{email}", email: "partner_#{email}",
first_name: "Demo (member)", first_name: "Eve",
last_name: "Maybe", last_name: "Bogle",
role: "member", role: "member",
password: "password", password: "Password1!",
onboarded_at: onboarded ? Time.current : nil onboarded_at: onboarded ? Time.current : nil
) )

View File

@@ -13,7 +13,7 @@ class FamilyExport < ApplicationRecord
scope :ordered, -> { order(created_at: :desc) } scope :ordered, -> { order(created_at: :desc) }
def filename 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 end
def downloadable? def downloadable?

View File

@@ -37,12 +37,12 @@ class Import::Row < ApplicationRecord
end end
private private
# In the Maybe system, positive quantities == "inflows" # In the Sure system, positive quantities == "inflows"
def apply_trade_signage_convention(value) def apply_trade_signage_convention(value)
value * (import.signage_convention == "inflows_positive" ? 1 : -1) value * (import.signage_convention == "inflows_positive" ? 1 : -1)
end 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) def apply_transaction_signage_convention(value)
if import.amount_type_strategy == "signed_amount" if import.amount_type_strategy == "signed_amount"
value * (import.signage_convention == "inflows_positive" ? -1 : 1) value * (import.signage_convention == "inflows_positive" ? -1 : 1)

View File

@@ -23,7 +23,7 @@ class MobileDevice < ApplicationRecord
app = Doorkeeper::Application.create!( app = Doorkeeper::Application.create!(
name: "Mobile App - #{device_id}", 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 scopes: "read_write", # Use the configured scope
confidential: false # Public client for mobile confidential: false # Public client for mobile
) )

View File

@@ -24,7 +24,7 @@ class PlaidAccount::Investments::BalanceCalculator
# Plaid considers "brokerage cash" and "cash equivalent holdings" to all be part of "cash balance" # 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" # For this reason, we must manually calculate the cash balance based on "total value" and "holdings value"
# See PlaidAccount::Investments::SecurityResolver for more details. # See PlaidAccount::Investments::SecurityResolver for more details.
def cash_balance def cash_balance

View File

@@ -63,7 +63,7 @@ class PlaidAccount::Investments::SecurityResolver
end end
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). # 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) # Plaid treats everything as a "holding" with a corresponding Security. For example, "brokerage cash" (USD)

View File

@@ -3,7 +3,7 @@
# categories we cannot directly assign Plaid categories as this would overwrite # categories we cannot directly assign Plaid categories as this would overwrite
# user data and create a confusing experience. # 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 # 1. Naive string matching via CategoryAliasMatcher
# 2. Rules-based matching set by user # 2. Rules-based matching set by user
# 3. AI-powered matching (also enabled by user via rules) # 3. AI-powered matching (also enabled by user via rules)

View File

@@ -1,7 +1,7 @@
class Provider::Plaid class Provider::Plaid
attr_reader :client, :region 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 MAX_HISTORY_DAYS = Rails.env.development? ? 90 : 730
def initialize(config, region: :us) 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) def get_link_token(user_id:, webhooks_url:, redirect_url:, accountable_type: nil, access_token: nil)
request_params = { request_params = {
user: { client_user_id: user_id }, user: { client_user_id: user_id },
client_name: "Maybe Finance", client_name: "Sure Finances",
country_codes: country_codes, country_codes: country_codes,
language: "en", language: "en",
webhook: webhooks_url, webhook: webhooks_url,
@@ -195,7 +195,7 @@ class Provider::Plaid
def get_additional_consented_products(accountable_type) def get_additional_consented_products(accountable_type)
return [] if eu? return [] if eu?
MAYBE_SUPPORTED_PLAID_PRODUCTS - [ get_primary_product(accountable_type) ] SUPPORTED_PLAID_PRODUCTS - [ get_primary_product(accountable_type) ]
end end
def eu? def eu?

View File

@@ -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 # 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. # for periodically checking active securities to ensure we can still fetch prices for them.
# #

View File

@@ -79,8 +79,8 @@ class SimplefinAccount::Processor
end end
# SimpleFin uses banking convention (expenses negative, income positive) # SimpleFin uses banking convention (expenses negative, income positive)
# Maybe expects opposite convention (expenses positive, income negative) # Sure expects opposite convention (expenses positive, income negative)
# So we negate the amount to convert from SimpleFin to Maybe format # So we negate the amount to convert from SimpleFin to Sure format
-parsed_amount -parsed_amount
rescue ArgumentError => e rescue ArgumentError => e
Rails.logger.error "Failed to parse SimpleFin transaction amount: #{amount_value.inspect} - #{e.message}" Rails.logger.error "Failed to parse SimpleFin transaction amount: #{amount_value.inspect} - #{e.message}"

View File

@@ -193,7 +193,7 @@ class User < ApplicationRecord
end end
def totp def totp
ROTP::TOTP.new(otp_secret, issuer: "Maybe Finance") ROTP::TOTP.new(otp_secret, issuer: "Sure Finances")
end end
def verify_backup_code?(code) def verify_backup_code?(code)

View File

@@ -3,11 +3,11 @@
<%= render "chats/ai_avatar" %> <%= render "chats/ai_avatar" %>
</div> </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"> <p class="text-gray-600 mb-4 text-sm text-center">
<% if Current.user.ai_available? %> <% 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 %> <% 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> 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. 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_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[ai_enabled]", value: true %>
<%= form.hidden_field "user[redirect_to]", value: "home" %> <%= 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 %>
<% end %> <% end %>

View File

@@ -2,7 +2,7 @@
<%= render "chats/ai_avatar" %> <%= render "chats/ai_avatar" %>
<div class="max-w-[85%] text-sm space-y-4 text-primary"> <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> <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 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

View File

@@ -27,7 +27,7 @@
<div class="bg-amber-50 border border-amber-200 rounded-lg p-3"> <div class="bg-amber-50 border border-amber-200 rounded-lg p-3">
<p class="text-sm text-amber-800"> <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> </p>
</div> </div>

View File

@@ -8,11 +8,11 @@
</div> </div>
<div class="flex items-center space-x-2 px-2 py-2 text-white gap-4"> <div class="flex items-center space-x-2 px-2 py-2 text-white gap-4">
<% if pending_session.present? %> <% 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 "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" %> <%= 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? %> <% 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" %> <%= 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 %> <% else %>
<p class="text-xs max-w-3xl text-right text-red-500">Something went wrong. Please contact us.</p> <p class="text-xs max-w-3xl text-right text-red-500">Something went wrong. Please contact us.</p>

View File

@@ -30,7 +30,7 @@
<% unless Security.provider %> <% unless Security.provider %>
<div class="alert alert-warning"> <div class="alert alert-warning">
<p> <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> </p>
</div> </div>
<% end %> <% end %>

View File

@@ -20,7 +20,7 @@
</div> </div>
<div class="space-y-2"> <div class="space-y-2">
<h2 class="text-3xl font-medium text-primary text-center"> <h2 class="text-3xl font-medium text-primary text-center">
Maybe Authorization Sure Authorization
</h2> </h2>
</div> </div>
</div> </div>

View File

@@ -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 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>
<div class="space-y-1 mb-6 text-center"> <div class="space-y-1 mb-6 text-center">
<h1 class="text-2xl font-medium md:text-2xl">What brings you to Maybe?</h1> <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 Maybe as your personal finance tool.</p> <p class="text-secondary text-sm">Select one or more goals that you have with using Sure as your personal finance tool.</p>
</div> </div>
<%= form_with model: @user do |form| %> <%= form_with model: @user do |form| %>

View File

@@ -17,7 +17,7 @@
<%= image_tag "logo-color.png", class: "w-16 mb-6" %> <%= image_tag "logo-color.png", class: "w-16 mb-6" %>
<p class="text-xl lg:text-3xl text-primary font-display font-medium"> <p class="text-xl lg:text-3xl text-primary font-display font-medium">
Try Maybe for 14 days. Try Sure for 14 days.
</p> </p>
<h2 class="text-xl lg:text-3xl font-display text-secondary font-medium mb-2"> <h2 class="text-xl lg:text-3xl font-display text-secondary font-medium mb-2">
@@ -25,13 +25,13 @@
</h2> </h2>
<p class="text-sm text-secondary text-center mb-8"> <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> </p>
<div class="w-full"> <div class="w-full">
<% if Current.family.can_start_trial? %> <% if Current.family.can_start_trial? %>
<%= render DS::Button.new( <%= render DS::Button.new(
text: "Try Maybe for 14 days", text: "Try Sure for 14 days",
href: subscription_path, href: subscription_path,
full_width: true, full_width: true,
data: { turbo: false } data: { turbo: false }
@@ -65,7 +65,7 @@
<div class="space-y-12"> <div class="space-y-12">
<div class="space-y-1.5 text-sm"> <div class="space-y-1.5 text-sm">
<p class="text-primary font-medium">Today</p> <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>
<div class="space-y-1.5 text-sm"> <div class="space-y-1.5 text-sm">
@@ -75,7 +75,7 @@
<div class="space-y-1.5 text-sm"> <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-primary font-medium">In 14 days (<%= 14.days.from_now.strftime("%B %d") %>)</p>
<p class="text-secondary">Your trial ends &mdash; subscribe to continue using Maybe</p> <p class="text-secondary">Your trial ends &mdash; subscribe to continue using Sure</p>
</div> </div>
</div> </div>
</div> </div>
@@ -107,7 +107,7 @@
<div class="flex flex-col gap-4 items-center"> <div class="flex flex-col gap-4 items-center">
<%= render "chats/ai_avatar" %> <%= 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>
<div class="flex flex-col gap-4 items-center"> <div class="flex flex-col gap-4 items-center">

View File

@@ -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="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"> <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" %> <%= icon "alert-triangle", class: "w-8 h-8 text-red-600" %>
</div> </div>
<h1 class="text-xl sm:text-2xl font-bold text-primary mb-2">Redis Configuration Required</h1> <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> </div>
<!-- Explanation --> <!-- Explanation -->
@@ -19,7 +19,7 @@
<%= icon "info", class: "w-5 h-5 text-amber-600 mt-0.5 mr-3 flex-shrink-0" %> <%= 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"> <div class="text-sm text-amber-800">
<p><strong>Why is Redis required?</strong></p> <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> </div>
</div> </div>
@@ -28,7 +28,7 @@
<div class="text-center space-y-4"> <div class="text-center space-y-4">
<%= render DS::Link.new( <%= render DS::Link.new(
text: "View Setup Guide", 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", variant: "primary",
size: "lg", size: "lg",
icon: "external-link", icon: "external-link",

View File

@@ -1,6 +1,6 @@
<%= content_for :page_title, "Create New API Key" %> <%= 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| %> <%= styled_form_with model: @api_key, url: settings_api_key_path, class: "space-y-4" do |form| %>
<%= form.text_field :name, <%= form.text_field :name,
placeholder: "e.g., My Budget App, Portfolio Tracker", placeholder: "e.g., My Budget App, Portfolio Tracker",

View File

@@ -40,7 +40,7 @@
{ label: t(".country") }, { label: t(".country") },
{ data: { auto_submit_form_target: "auto" } } %> { 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 %>
<% end %> <% end %>
</div> </div>

View File

@@ -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"> <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> </div>

View File

@@ -32,11 +32,11 @@
<h2 class="text-xl lg:text-3xl font-display font-medium mb-2"> <h2 class="text-xl lg:text-3xl font-display font-medium mb-2">
<span class="text-secondary">Unlock</span> <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> <span class="text-secondary">today</span>
</h2> </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| %> <%= form_with url: new_subscription_path, method: :get, class: "max-w-xs", data: { turbo: false } do |form| %>
<div class="space-y-4 mb-6"> <div class="space-y-4 mb-6">
@@ -46,7 +46,7 @@
<div class="text-center space-y-2"> <div class="text-center space-y-2">
<%= render DS::Button.new( <%= render DS::Button.new(
text: "Subscribe and unlock Maybe", text: "Subscribe and unlock Sure",
variant: "primary", variant: "primary",
full_width: true full_width: true
) %> ) %>

View File

@@ -20,10 +20,10 @@
<div class="px-4 py-3 border-t border-tertiary"> <div class="px-4 py-3 border-t border-tertiary">
<p class="text-sm"> <p class="text-sm">
<span class="font-medium text-primary">Version:</span> <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? %> <% if Sure.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" %>) (<%= link_to Sure.commit_sha.first(7), "https://github.com/we-promise/sure/commit/#{Sure.commit_sha}", target: "_blank", class: "hover:underline" %>)
<% end %> <% end %>
</p> </p>
</div> </div>

View File

@@ -28,9 +28,9 @@
# #
x-db-env: &db_env x-db-env: &db_env
POSTGRES_USER: ${POSTGRES_USER:-maybe_user} POSTGRES_USER: ${POSTGRES_USER:-sure_user}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-maybe_password} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-sure_password}
POSTGRES_DB: ${POSTGRES_DB:-maybe_production} POSTGRES_DB: ${POSTGRES_DB:-sure_production}
x-rails-env: &rails_env x-rails-env: &rails_env
<<: *db_env <<: *db_env

View File

@@ -6,7 +6,7 @@ require "rails/all"
# you've limited to :test, :development, or :production. # you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups) Bundler.require(*Rails.groups)
module Maybe module Sure
class Application < Rails::Application class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version. # Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.2 config.load_defaults 7.2

View File

@@ -7,4 +7,4 @@ test:
production: production:
adapter: redis adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: maybe_production channel_prefix: sure_production

View File

@@ -9,12 +9,12 @@ default: &default
development: development:
<<: *default <<: *default
database: <%= ENV.fetch("POSTGRES_DB") { "maybe_development" } %> database: <%= ENV.fetch("POSTGRES_DB") { "sure_development" } %>
test: test:
<<: *default <<: *default
database: <%= ENV.fetch("POSTGRES_DB") { "maybe_test" } %> database: <%= ENV.fetch("POSTGRES_DB") { "sure_test" } %>
production: production:
<<: *default <<: *default
database: <%= ENV.fetch("POSTGRES_DB") { "maybe_production" } %> database: <%= ENV.fetch("POSTGRES_DB") { "sure_production" } %>

View File

@@ -24,7 +24,7 @@ Rails.application.configure do
} }
# Set default sender email for tests # 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. # Show full error reports and disable caching.
config.consider_all_requests_local = true config.consider_all_requests_local = true

View File

@@ -2,8 +2,8 @@ require "sidekiq/web"
if Rails.env.production? if Rails.env.production?
Sidekiq::Web.use(Rack::Auth::Basic) do |username, password| Sidekiq::Web.use(Rack::Auth::Basic) do |username, password|
configured_username = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_USERNAME", "maybe")) configured_username = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_USERNAME", "sure"))
configured_password = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_PASSWORD", "maybe")) 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(username), configured_username) &&
ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(password), configured_password) ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(password), configured_password)

View File

@@ -1,4 +1,4 @@
module Maybe module Sure
class << self class << self
def version def version
Semver.new(semver) Semver.new(semver)

View File

@@ -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 "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 "privacy", to: redirect("about:blank")
get "terms", to: redirect("https://maybefinance.com/tos") get "terms", to: redirect("about:blank")
# Defines the root path route ("/") # Defines the root path route ("/")
root "pages#dashboard" root "pages#dashboard"

View File

@@ -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 # These are the only OAuth apps that will exist - external developers use API keys
# Maybe iOS App # Sure iOS App
ios_app = Doorkeeper::Application.find_or_create_by(name: "Maybe iOS") do |app| ios_app = Doorkeeper::Application.find_or_create_by(name: "Sure iOS") do |app|
app.redirect_uri = "maybe://oauth/callback" app.redirect_uri = "sureapp://oauth/callback"
app.scopes = "read_accounts read_transactions read_balances" app.scopes = "read_accounts read_transactions read_balances"
app.confidential = false # Public client (mobile app) app.confidential = false # Public client (mobile app)
end end

View File

@@ -1,6 +1,6 @@
# Chat API Documentation # 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 ## Authentication

View File

@@ -170,7 +170,7 @@ After doing this, make sure and restart the app:
```bash ```bash
docker compose pull # This pulls the "latest" published image from GHCR docker compose pull # This pulls the "latest" published image from GHCR
docker compose build # This rebuilds the app with updates 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 ## Troubleshooting
@@ -189,5 +189,5 @@ By running the commands below, you will delete your existing Sure database and "
docker compose down docker compose down
docker volume rm sure_postgres-data # this is the name of the volume the DB is mounted to docker volume rm sure_postgres-data # this is the name of the volume the DB is mounted to
docker compose up 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
``` ```

View File

@@ -1,7 +1,7 @@
# Benchmarking requires a production-like data sample, so requires some up-front setup. # 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 # 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 maybe_benchmarking DB # 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` # 3. Run `rake benchmark_dump:06_setup_bench_user`
# 4. Run locally, find endpoint needed # 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` # 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| Benchmark.ips do |x|
x.config(time: 30, warmup: 10) 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 scope = family.transactions.active
# x.report("IncomeStatement::Totals") do # x.report("IncomeStatement::Totals") do

View File

@@ -10,7 +10,7 @@ namespace :data_migration do
eu_items.find_each do |item| eu_items.find_each do |item|
request = Plaid::ItemWebhookUpdateRequest.new( request = Plaid::ItemWebhookUpdateRequest.new(
access_token: item.access_token, 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) provider.client.item_webhook_update(request)

View File

@@ -14,7 +14,7 @@ class CustomAuth < DerailedBenchmarks::AuthHelper
def call(env) def call(env)
# Make sure this user is created in the DB with realistic data before running benchmarks # 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}" Rails.logger.debug "Found user for benchmarking: #{user.email}"

View File

@@ -5,7 +5,7 @@ class DialogComponentPreview < ViewComponent::Preview
dialog.with_header(title: "Sample modal title") dialog.with_header(title: "Sample modal title")
dialog.with_body do dialog.with_body do
"Welcome to Maybe! This is some test modal content." "Welcome to Sure! This is some test modal content."
end end
dialog.with_action(cancel_action: true, text: "Cancel", variant: "outline") dialog.with_action(cancel_action: true, text: "Cancel", variant: "outline")

View File

@@ -2,7 +2,7 @@ require "test_helper"
class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
test "impersonation session logs all activity for auditing" do 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) impersonated = users(:family_member)
impersonator_session = impersonation_sessions(:in_progress) impersonator_session = impersonation_sessions(:in_progress)
@@ -16,7 +16,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
end end
test "super admin can request an impersonation session" do 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 } } post impersonation_sessions_path, params: { impersonation_session: { impersonated_id: users(:family_member).id } }
@@ -25,7 +25,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
end end
test "super admin can join and leave an in progress impersonation session" do 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) impersonator_session = impersonation_sessions(:in_progress)
@@ -52,7 +52,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
end end
test "super admin can complete an impersonation session" do 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) impersonator_session = impersonation_sessions(:in_progress)
@@ -77,7 +77,7 @@ class ImpersonationSessionsControllerTest < ActionDispatch::IntegrationTest
end end
test "super admin cannot accept an impersonation session" do 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) impersonator_session = impersonation_sessions(:in_progress)

View File

@@ -31,7 +31,7 @@ class MfaControllerTest < ActionDispatch::IntegrationTest
test "enables MFA with valid code" do test "enables MFA with valid code" do
@user.setup_mfa! @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 } post mfa_path, params: { code: totp.now }
@@ -70,7 +70,7 @@ class MfaControllerTest < ActionDispatch::IntegrationTest
sign_out sign_out
post sessions_path, params: { email: @user.email, password: user_password_test } 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 } post verify_mfa_path, params: { code: totp.now }

View File

@@ -82,7 +82,7 @@ class OnboardingsControllerTest < ActionDispatch::IntegrationTest
test "should get goals" do test "should get goals" do
get goals_onboarding_url get goals_onboarding_url
assert_response :success assert_response :success
assert_select "h1", text: /What brings you to Maybe/i assert_select "h1", text: /What brings you to Sure/i
end end
test "should get trial" do test "should get trial" do

View File

@@ -26,7 +26,7 @@ class SubscriptionsControllerTest < ActionDispatch::IntegrationTest
end end
assert_redirected_to root_path 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_equal "trialing", @family.subscription.status
assert_in_delta Subscription::TRIAL_DAYS.days.from_now, @family.subscription.trial_ends_at, 1.minute assert_in_delta Subscription::TRIAL_DAYS.days.from_now, @family.subscription.trial_ends_at, 1.minute
end end
@@ -71,6 +71,6 @@ class SubscriptionsControllerTest < ActionDispatch::IntegrationTest
get success_subscription_url(session_id: "test-session-id") get success_subscription_url(session_id: "test-session-id")
assert @family.subscription.active? 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
end end

View File

@@ -1,4 +1,4 @@
in_progress: in_progress:
impersonator: maybe_support_staff impersonator: sure_support_staff
impersonated: family_member impersonated: family_member
status: in_progress status: in_progress

View File

@@ -2,17 +2,17 @@ empty:
family: empty family: empty
first_name: User first_name: User
last_name: One last_name: One
email: user1@email.com email: user1@example.com
password_digest: $2a$12$XoNBo/cMCyzpYtvhrPAhsubG21mELX48RAcjSVCRctW8dG8wrDIla password_digest: $2a$12$XoNBo/cMCyzpYtvhrPAhsubG21mELX48RAcjSVCRctW8dG8wrDIla
onboarded_at: <%= 3.days.ago %> onboarded_at: <%= 3.days.ago %>
role: admin role: admin
ai_enabled: true ai_enabled: true
maybe_support_staff: sure_support_staff:
family: empty family: empty
first_name: Support first_name: Support
last_name: Admin last_name: Admin
email: support@maybefinance.com email: support@sure.am
password_digest: $2a$12$XoNBo/cMCyzpYtvhrPAhsubG21mELX48RAcjSVCRctW8dG8wrDIla password_digest: $2a$12$XoNBo/cMCyzpYtvhrPAhsubG21mELX48RAcjSVCRctW8dG8wrDIla
role: super_admin role: super_admin
onboarded_at: <%= 3.days.ago %> onboarded_at: <%= 3.days.ago %>

View File

@@ -8,7 +8,7 @@ class OauthMobileTest < ActionDispatch::IntegrationTest
sign_in(@user) sign_in(@user)
@oauth_app = Doorkeeper::Application.create!( @oauth_app = Doorkeeper::Application.create!(
name: "Maybe Mobile App", name: "Sure Mobile App",
redirect_uri: "sureapp://oauth/callback", redirect_uri: "sureapp://oauth/callback",
scopes: "read" scopes: "read"
) )

View File

@@ -8,7 +8,7 @@ class EmailConfirmationMailerTest < ActionMailer::TestCase
mail = EmailConfirmationMailer.with(user: user).confirmation_email mail = EmailConfirmationMailer.with(user: user).confirmation_email
assert_equal I18n.t("email_confirmation_mailer.confirmation_email.subject"), mail.subject assert_equal I18n.t("email_confirmation_mailer.confirmation_email.subject"), mail.subject
assert_equal [ user.unconfirmed_email ], mail.to 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 assert_match "confirm", mail.body.encoded
end end
end end

View File

@@ -29,7 +29,7 @@ class FamilyExportTest < ActiveSupport::TestCase
test "filename is generated correctly" do test "filename is generated correctly" do
travel_to Time.zone.local(2024, 1, 15, 14, 30, 0) do travel_to Time.zone.local(2024, 1, 15, 14, 30, 0) do
export = @family.family_exports.create! 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 assert_equal expected_filename, export.filename
end end
end end

View File

@@ -9,13 +9,13 @@ class ImpersonationSessionTest < ActiveSupport::TestCase
assert_raises(ActiveRecord::RecordInvalid) do assert_raises(ActiveRecord::RecordInvalid) do
ImpersonationSession.create!( ImpersonationSession.create!(
impersonator: regular_user, impersonator: regular_user,
impersonated: users(:maybe_support_staff) impersonated: users(:sure_support_staff)
) )
end end
end end
test "super admin cannot be impersonated" do test "super admin cannot be impersonated" do
super_admin = users(:maybe_support_staff) super_admin = users(:sure_support_staff)
assert super_admin.super_admin? assert super_admin.super_admin?
@@ -28,7 +28,7 @@ class ImpersonationSessionTest < ActiveSupport::TestCase
end end
test "impersonation session must have different impersonator and impersonated" do 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 assert_raises(ActiveRecord::RecordInvalid) do
ImpersonationSession.create!( ImpersonationSession.create!(

View File

@@ -106,7 +106,7 @@ class UserTest < ActiveSupport::TestCase
user = users(:family_member) user = users(:family_member)
user.setup_mfa! 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 valid_code = totp.now
assert user.verify_otp?(valid_code) 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{otpauth://totp/}, user.provisioning_uri
assert_match %r{secret=#{user.otp_secret}}, 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 end
test "ai_available? returns true when openai access token set in settings" do test "ai_available? returns true when openai access token set in settings" do

View File

@@ -12,7 +12,7 @@ class ChatsTest < ApplicationSystemTestCase
visit root_path visit root_path
within "#chat-container" do within "#chat-container" do
assert_selector "h3", text: "Enable Maybe AI" assert_selector "h3", text: "Enable AI Chats"
end end
end end

View File

@@ -38,7 +38,7 @@ class OnboardingsTest < ApplicationSystemTestCase
# Should redirect to goals page # Should redirect to goals page
assert_current_path goals_onboarding_path assert_current_path goals_onboarding_path
assert_text "What brings you to Maybe?" assert_text "What brings you to Sure?"
end end
test "preferences page renders chart without errors" do test "preferences page renders chart without errors" do
@@ -137,7 +137,7 @@ class OnboardingsTest < ApplicationSystemTestCase
visit goals_onboarding_path visit goals_onboarding_path
assert_text "What brings you to Maybe?" assert_text "What brings you to Sure?"
assert_button "Next" assert_button "Next"
end end

View File

@@ -5,7 +5,7 @@ http_interactions:
uri: https://sandbox.plaid.com/link/token/create uri: https://sandbox.plaid.com/link/token/create
body: body:
encoding: UTF-8 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: headers:
Content-Type: Content-Type:
- application/json - application/json

View File

@@ -114,13 +114,13 @@ http_interactions:
"postal_code": "12345", "postal_code": "12345",
"state": null "state": null
}, },
"email": "user@sure.local", "email": "user@example.com",
"name": "Test Checkout User", "name": "Test Checkout User",
"phone": null, "phone": null,
"tax_exempt": "none", "tax_exempt": "none",
"tax_ids": [] "tax_ids": []
}, },
"customer_email": "user@sure.local", "customer_email": "user@example.com",
"discounts": [], "discounts": [],
"expires_at": 1746368350, "expires_at": 1746368350,
"invoice": "in_1RKguoQT2jbOS8G0PuBVklxw", "invoice": "in_1RKguoQT2jbOS8G0PuBVklxw",