CHANGELOG.md
Rama main · réplica de lectura del repositorio original.
# Changelog
Every released version, newest first. The release workflow copies the section
for a version into its GitHub release, and the dashboard reads that back when
it checks whether a newer version exists. A `### Security` heading here is what
makes the dashboard's update notice loud rather than quiet, so the wording
below is not decoration.
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## 0.6.1
### Fixed
- Changing a product's subdomain in Settings no longer stops sales from
being tracked. Supaffi asks before saving, then moves its Stripe webhook to
the new address. If the webhook was not made by Supaffi, or Stripe refuses
the change, Settings shows the address to set in Stripe.
- Voiding a commission and confirming a self-referral now ask first, since
neither can be undone.
- Today, This week and This month on the overview compare with the same
stretch of the previous day, week or month.
- The Sales column on the Affiliates list no longer counts refunded or
voided sales, so it matches the overview.
- A referred customer who cancels and then subscribes again through the
same referral counts as still paying.
## 0.6.0
### Added
- Optional email, through your own provider. Connect it in a product's
Settings, under Email: pick Resend, Brevo or Gmail and paste a key, or
enter any SMTP server. Supaffi sends a test email and only saves settings
that work. Each product has its own, so its affiliates hear from its own
domain.
- With email on, you hear when someone joins, when a referred customer
first buys, and when a sale looks like a self-referral. Affiliates get a
welcome with their link, a note on a referred customer's first sale and
when they are paid. Joins, sales and affiliate emails each have a switch.
- Affiliates reset a forgotten password themselves from the login page when
the product has email on. Without email, nothing changes: you still copy
them a password link from their panel.
## 0.5.0
### Added
- Promo codes. Pick one of your Stripe coupons as a program's discount, and
each affiliate claims their own code for it from their dashboard. A
customer who uses the code credits the affiliate, even without clicking
their link. You can also create a code for an affiliate, link a code you
already have in Stripe, or turn a code off.
### Changed
- Promo codes need a Stripe key that can read coupons and create promotion
codes. Your current key keeps working for everything else. The screens
that need the new permissions link to replacing the key, with them
already ticked.
- New products propose `affiliates.` as the affiliate subdomain instead of
`go.`. Existing products keep theirs.
## 0.4.0
### Security
- Changing an affiliate's password now signs out every session they had
before, so a hijacked affiliate account can no longer keep changing its
payout details after a reset.
- If you run Supaffi behind your own reverse proxy, update its config from
the README. The previous example let visitors fake their address, which
switched off the login and signup limits.
### Added
- Sales through Stripe Payment Links, buy buttons and pricing tables earn
commissions. The tracking script is all you add. A link that already
carries your own client reference is left alone.
### Fixed
- Mark paid says when a payout was already marked paid, instead of looking
like it worked.
- Buy links follow the latest affiliate click, even on a page opened before
it.
## 0.3.4
### Changed
- The affiliate signup page and dashboard no longer assume you sell
subscriptions. The second signup tile reads "Earn on" (every payment, a
number of months, or the first payment only), and the terms line says
"of every payment" instead of "forever".
### Fixed
- Customers who bought once are no longer counted as "still paying" on the
affiliate dashboard or the Affiliates page. Only referred subscribers count,
and the affiliate's Referrals card appears once they have one.
## 0.3.3
### Fixed
- Affiliates land on their dashboard after logging in or signing up. Before,
they were sent back to the login page, though the login had worked.
## 0.3.2
### Changed
- Your affiliate address now opens the signup of your first open program,
instead of the login. Share it as your affiliate link. Other programs keep
their own signup links, and the copy buttons give the right one for each.
A logged in affiliate goes straight to their dashboard, and the login page
links to the signup.
- Onboarding no longer asks for a program name. The first program is named
after the product, and the step is called Commission.
- Open Cloudflare in onboarding lands on the product's DNS records instead of
the list of domains.
## 0.3.1
### Security
- Update soon. This release moves Next.js and several other packages past
known security flaws, some of them rated critical.
- The image no longer ships the build and test tools or npm, which removes
most of the other flaws scanners reported in it.
### Changed
- A new Payouts page lists what you owe, one row per affiliate and currency,
with their payout details ready to copy and a Mark paid button. Past payouts
are grouped by payment. The Commissions page no longer holds this list.
- Affiliates pick a payout method from a list and enter one value. Details
saved before this release keep working.
- A program with Public signup turned off shows an invite only page instead
of the signup form.
- Forms keep what you typed when a submit is refused. The website field
accepts a bare domain.
- The tracking check counts a click from the past week as proof the script
is installed.
## 0.3.0
### Changed
- Supaffi no longer sends email, and setup no longer asks for a Resend key or
a sending domain. Affiliates sign up with an email and a password and log in
with them.
- Affiliates who signed up before this release have no password yet. Open each
one in Affiliates, press Create password link and send them the link. It
works once, for 3 days. The same link resets a forgotten password.
- The stored Resend keys are deleted on upgrade.
### Fixed
- Your login page no longer answers on a product's affiliate domain. Opening
that domain's address on its own goes to the affiliate login.
## 0.2.7
### Security
- Replace your Stripe key once: open Settings, press Replace on the Stripe key
row and create the new key from the button there. Check that Disputes and
Checkout Sessions are set to Read. Supaffi uses Disputes to hold a commission
while its sale is disputed, and Checkout Sessions to take the tax off a
one-time sale. Until you replace it, a disputed commission stays held, and a
one-time sale retries for about two days before it stops earning.
- Each program now has a Public signup switch. Turn it off for a tier you move
affiliates into yourself. Before, anyone who guessed a program's signup
address could join it.
### Fixed
- Two customers on the same office or mobile network each get their own
referral. Before, they could share one, and the second sale could earn the
affiliate nothing.
- A Stripe outage while a sale is recorded retries the sale instead of
skipping its refund, dispute and card checks. A dispute holds its commission
while it retries.
- No Stripe error text reaches the server log or a failed event's stored
error, only its type and code.
- A commission waits while its sale is disputed. It goes back to normal if you
win the dispute and is cancelled if you lose it before paying.
- A dispute that reaches Supaffi before its sale is applied when the sale is
recorded.
- You can confirm a self referral from any of its commissions, whatever its
status.
- A renewal earns only on the subscription the affiliate referred and the
products bought through the referral. One-off charges, manual invoices, a
switch to another Stripe product and money you mark as paid outside Stripe
earn nothing.
- Cancelling and subscribing again, or changing plan through a new checkout,
no longer starts the commission duration over. Each referral gets one.
- Setting `supaffi` to `false` on the invoice, subscription or customer now
excludes a sale at checkout and on every renewal. Set it before the customer
pays. A sale Supaffi cannot check earns nothing and is noted in the server
log.
- A subscription's first payment earns only on what the customer paid, like a
renewal. Before, credit balance on a first purchase still earned, which the
0.2.4 notes did not say.
- A one-time sale earns on the price before tax, including tax inside the
price. If Stripe does not say how much tax it held, it earns nothing and is
noted in the server log.
- A refund or lost chargeback on a one-time sale with a post-purchase invoice
now lowers or cancels its commission.
### Changed
- A paid commission is final. A refund or lost chargeback after you paid
changes nothing, and nothing is taken off the affiliate's next payout.
- Mark paid records exactly the commissions and amounts you saw. Ones you
cancelled in the meantime are skipped, and the page says how many. A page
open for more than an hour has to be shown again first, so a refund that
landed meanwhile is not recorded as paid.
- One-off items sold with a subscription, such as a setup fee, no longer earn.
## 0.2.6
### Fixed
- Mark paid records the amounts you saw, so a payout is never recorded for
less than the total you sent.
- Owed and payable now are the same figures on every screen.
- An affiliate's Earned figure leaves out its comparison when the earlier
period came to nothing.
- Two payouts to the same affiliate on the same day show as two payments in
their history, each with the time it was made.
- Processed messages from Stripe older than 90 days are removed, so the
database no longer grows forever.
- A message from Stripe whose signature does not verify is now noted in the
server log instead of being refused in silence.
### Changed
- The products list says owed instead of pending.
## 0.2.5
### Fixed
- When several products share one Stripe account, a renewal now pays only the
affiliate who referred that specific subscription, not whoever referred the
same customer to a different product.
- A subscription that did not start through a referred checkout, such as one
created directly in the Stripe Dashboard, never earns a commission.
- Programs that pay for a set number of months count them from the
subscription's first payment.
- A one-time commission is paid on the first real payment after a free trial.
- Every renewal paid with a card that matches one of the affiliate's own
Stripe customers is flagged for review, not only the first purchase.
- Cancelling a subscription marks only that product's referral as cancelled.
Other subscriptions the same referral brought keep paying.
- Referrals made before this update are recognised the first time one of
their invoices arrives, but only if their first purchase had already earned
a commission. If it had not, for example a free trial that later converted,
a first period discounted to nothing, a first purchase you excluded, or a
sale made on 0.2.4 that was skipped because its tax could not be read, that
referral stops earning renewals from this update on, and a cancellation of
it is not counted either.
### Changed
- Confirming a self referral now cancels every commission from that referral
that has not been paid yet, and stops it earning anything later. Commissions
already paid are left as they are. The button says so.
- Self referrals confirmed before this update have their unpaid commissions
cancelled by the update itself.
## 0.2.4
### Security
- Replace your Stripe key once: open Settings, press Replace on the Stripe key
row and create the new key from the button there. The new key can also read
charges, which Supaffi uses to catch refunds made right after a sale. Until
you replace it, everything keeps working as it did.
### Fixed
- Commissions are worked out on the price before tax and shipping, whether
your prices include tax or add it at checkout. Discounts still lower it.
- Revenue on the overview follows the same rule. Sales recorded before this
version keep the figures they had, so a period that spans the update can
look a little lower than the one before it.
- A first purchase or a renewal that comes to nothing, or is paid from the
customer's credit balance, no longer adds an empty commission. A renewal
paid partly from that balance now earns only on the part actually paid.
- A refund that reaches Supaffi before the sale it belongs to still lowers or
cancels that sale's commission.
- A commission cancelled by a lost chargeback now says so plainly, for you
and for the affiliate.
- Very large sales in currencies such as the Vietnamese dong or the
Indonesian rupiah are recorded instead of failing.
- A sale whose tax cannot be read earns nothing rather than a wrong amount,
and is noted in the server log.
### Changed
- If Supaffi cannot add the missing events to a product's webhook when it
starts up, it now writes that to the server log instead of showing a
warning in the dashboard.
## 0.2.3
### Security
- Webhook events interrupted by a restart are picked up again, and failing
events are retried for about two days instead of eight minutes, so sales and
refunds are no longer lost.
- A checkout paid by a delayed method, such as a bank debit, only earns a
commission once the payment actually succeeds. Existing Stripe connections
get the extra events added automatically at startup.
- A lost chargeback takes the commission back, the same way a full refund does.
- A sale on one product can no longer earn a commission for another product's
affiliate.
- Paying, voiding and refunds landing at the same moment can no longer leave a
commission in the wrong state, and refunds arriving out of order can no
longer raise a commission back up.
- Owner login limits can no longer be bypassed, used to crash the server, or
used by a stranger to lock the owner out.
- Login and signup emails to affiliates are rate limited, and a login link is
only used when the affiliate presses Log in, so email scanners no longer
spend it.
- A renamed or deleted referral code can no longer be claimed by another
affiliate.
- The tracking script and click endpoint are hardened and rate limited, and the
dashboards can no longer be embedded in another site.
### Fixed
- Long lists show a short run of page numbers instead of every page.
- The payable tabs list sales before the refund adjustments against them.
### Added
- Every figure on the overview says how it compares with the period before,
in green, red or grey.
- A top affiliates card on the owner's overview, with a bar under each name
showing how close they are to the leader.
### Changed
- The timeframe is chosen once, at the top of the overview, and every figure,
the chart and the top affiliates follow it.
- The owner's Signups figure is gone. It counted affiliates joining, which read
like customers. Revenue takes its place.
- What needs your attention is a set of cards you can open, and a commission
flagged as a possible self referral stands out in red.
- Amounts are written with their currency symbol and thousands separators,
and every total leads with the currency the chart is drawn in.
- The chart's bars and line animate in again whenever the timeframe changes.
- A tighter, even margin around the sidebar and the content, one corner
rounding everywhere, and reworked product and account menus. The account
menu now shows the version and whether an update is available.
- Both dashboards stack and scroll properly on phones and tablets.
## 0.2.2
### Added
- A chart on both dashboards: the clicks affiliates sent, over the money those
clicks turned into. The owner's bars are the sale with the commission drawn
on top of what they keep, so one bar says both what came in and what it
cost. Eight windows to choose from, by the hour for a single day and by the
month for a year, kept in the address so a reload and a shared link land on
the same view.
- A currency switcher, for the rare product that sells in more than one. Money
is never added across currencies, so the bars draw one and the tooltip lists
the rest.
- A command that fills an instance with demo traffic, for looking at the
dashboards before a product has any.
### Changed
- Setting up is six steps instead of nine. The webhook screen is gone: the key
is made from a link that already grants what is needed, and saving it creates
the endpoint. The two Resend screens are one, because both halves are done in
the same browser tab in one sitting. The rail no longer counts the install and
the account as steps, which only made the flow look longer than it is.
- Setup screens appear at once and fill their lights in behind you. Pressing
Continue used to hold the button down for a few seconds, with nothing on
screen to say why.
- Both dashboards sit on a grounded sidebar with the content floating above it,
and every card has real depth rather than a hairline on white.
- The address proposed for a new product is now `go.` rather than `affiliates.`,
which is shorter in every affiliate link and stops the login emails going out
from `affiliates@affiliates.yoursite.com`.
- What can be paid is a list rather than a row of buttons, so an affiliate owed
in two currencies reads as two payouts rather than a duplicate.
### Fixed
- A tick on the setup rail now means the check passed. Walking past a step used
to be enough to mark it done, so a deleted record and a sending domain that
was never added both read as finished.
- The certificate check no longer fails on hosts that cannot route a request
from the server back to its own address. The site was reachable from
anywhere on the internet and the instance alone could not see it.
- Voided commissions and refund adjustments no longer count as sales, which
could leave a day showing a sale with no money against it.
- Checks against Stripe and Resend give up rather than hanging, so a screen
cannot be left saying "checking" until it is reloaded.
- Every check that runs now writes a line to the log, with how long the outside
world took to answer. A self-hosted instance had no way to see any of it.
## 0.1.1
### Fixed
- Updating stopped silently after taking its backup and applied nothing. The
install script is piped into a shell, so the shell reads it from standard
input, and the backup step attached the database container to that same
input and consumed the rest of the script. Nothing was printed and nothing
was broken, but the instance stayed on the version it was already running.
Fresh installs were never affected, since only an update takes a backup.
## 0.1.0
First release.
### Added
- One command self-hosted install. It asks nothing, installs Docker if it is
missing, works out whether it can own ports 80 and 443, and prints an address
and a setup token.
- The dashboard is served over HTTPS on the server's own address, so a fresh
install is reachable with no domain and no DNS record.
- A setup token, so a stranger who finds the server first cannot claim it.
- Affiliate programs, each on its own hostname, with certificates issued
automatically on first request.
- Stripe ingestion: sales are attributed to affiliates and become commissions
after the holding period.
- Affiliate signup, magic link login, referral links, and an affiliate
dashboard.
- Rate limiting on owner login, which matters because the login form now sits
on a public address.
- Published images for Intel and ARM servers, so nothing is compiled on the
operator's machine.