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):
- Email: `user@sure.local`
- Password: `password`
- Email: `user@example.com`
- Password: `Password1!`
For further instructions, see guides below.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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
)

View File

@@ -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?

View File

@@ -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)

View File

@@ -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
)

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"
#
# 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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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?

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

View File

@@ -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}"

View File

@@ -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)

View File

@@ -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 %>

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 %>

View File

@@ -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>

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>
<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| %>

View File

@@ -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 &mdash; subscribe to continue using Maybe</p>
<p class="text-secondary">Your trial ends &mdash; 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">

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="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",

View File

@@ -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",

View File

@@ -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>

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">
<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>

View File

@@ -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
) %>

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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" } %>

View File

@@ -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

View File

@@ -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)

View File

@@ -1,4 +1,4 @@
module Maybe
module Sure
class << self
def version
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 "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"

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
# 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

View File

@@ -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

View File

@@ -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
```

View File

@@ -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

View File

@@ -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)

View File

@@ -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}"

View File

@@ -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")

View File

@@ -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)

View File

@@ -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 }

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -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 %>

View File

@@ -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"
)

View File

@@ -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

View File

@@ -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

View File

@@ -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!(

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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",