AI Investments 6.1.6
11 August 2026
This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.
AI Investment v6.1.6
Release Date: August 11, 2026 Tags: INVESTMENTS, SETTLEMENT, MONEY, DATA-LOSS, SECURITY, RELIABILITY, BUG-FIXES
Overview
A money-correctness release. Three of these fixes change what happens to a customer's money, and all three are worth a look at your existing records.
Deleting an AI investment duration removed every investment attached to it — including ones still running and holding customer principal — with no refund and no ledger entry. Cancelling an investment refunded the asset read off the market label rather than the asset actually taken from the customer, and that label was assembled from two fields the customer's own request supplied. And an admin completing or cancelling an investment in the same moment the hourly settlement job reached it was authorised by a status nothing was holding, so the platform could pay out both the settlement and the full principal for one investment.
Read the Upgrade Notes before updating, and update Core first. Requires Core v6.6.3.
Update Instructions
pnpm updatorNothing to configure and no setting changes. There is no automatic data repair, so see Upgrade Notes for what to inspect afterwards.
Upgrade Notes
- If you have ever deleted an AI investment duration — or deleted a plan permanently rather than hiding it — every investment that referenced it was removed from the database at that moment, running ones included. No refund was issued and no ledger entry was written, so nothing on an admin screen names them. What survives is the customer's original debit, sitting in their history with no settlement and no refund against it. Those are the customers to reconcile by hand, and there is no automated way to find them from the investment records themselves, because those records are gone.
- Look through your AI investments for any whose market label carries more than one slash —
X/BTC/USDTwhere every ordinary row readsBTC/USDT. A row like that can only come from a crafted request. If it was cancelled, the customer was credited their refund in the second asset of that label and never got back the asset that was actually debited, so they hold a balance they are not owed in one asset and are still short their principal in another. Both sides need correcting by hand. - Look for an investment an admin completed or cancelled within moments of its maturity. In the customer's history it shows as a settlement credit and a full principal refund against the same investment, seconds apart, each under its own reference. Only one of the two was owed.
- Customers whose plan was deleted while their investment was still running were paid on maturity but never told — no completion email and no in-app record. Their balance is correct; only the notice is missing, and you may want to tell them yourself.
Fixed
Deleting a plan or a duration destroyed the investments running on it
The admin doors that remove an AI investment plan or duration went straight at the row with no check of what depended on it, and the database is set up to take every investment attached to a plan or a duration with it. Deleting one duration therefore erased every investment on that duration — active ones still holding customer principal, and completed ones that are the platform's only record of money it had already paid. There was no refund, no ledger entry and no trace. A duration is never merely hidden, so that erasure happened on an ordinary delete, without anyone asking for a permanent one; a plan is hidden by default, and there the danger was different — a hidden plan puts the investments still running on it out of the settlement job's reach, so they would simply never pay out.
- Fixed the plan and duration delete doors, single and bulk, now count what depends on the row before removing anything. A delete that will reach the database for real — every duration delete, and a plan delete when a permanent one is requested — is refused while any investment still references it. A plan delete that only hides the row is refused while any investment on it is still active. The refusal says how many investments are in the way and tells the operator to settle or cancel them first, cancelling being the route that returns each customer's principal.
A cancelled investment could be refunded in the wrong asset
The market an investment belongs to was stored as the two asset codes from the purchase request joined by a slash, and the cancellation door worked out which wallet to refund by splitting that text back apart. The debit, however, was always taken from the wallet holding the second code. The two agreed only for as long as neither code contained a slash of its own, and nothing checked. A purchase that put a slash inside the first code moved the boundary: 1,000 USDT was debited, and cancelling the same investment credited 1,000 BTC.
- Fixed a cancellation now refunds the wallet the money was actually debited from, identified from the original debit itself, which nothing the customer sends can steer. The refund's ledger entry is denominated in that wallet's own asset, so it can never name a currency the wallet does not hold, and a cancellation is refused outright if the debit on record names a wallet belonging to somebody else. Investments created before this release that have no matching debit on record still fall back to the old reading, because there is nothing better to go on.
- Fixed the purchase door now refuses an asset code that is not a plain code — a slash, a space or any other punctuation is rejected, with a message naming the offending field. Ordinary purchases are unaffected — the codes your markets use have always been plain.
An admin completing or cancelling an investment during settlement could pay it twice
The admin status change read the investment's status once, without a lock and outside the transaction that then moved the money, and never asked again. So an admin clicking Cancel in the same second the hourly settlement job reached that investment was let through on a status that had already changed. The job would credit the payout and mark the investment complete; the admin's request would then refund the full principal on top. The payout and the refund carry different references and different idempotency keys, so nothing downstream could recognise them as the same event and collapse them. A 2,000 stake on a plan paying 10% could pay out 4,200.
- Fixed both admin doors now re-read the investment under a lock as the first thing inside the transaction that moves money, and re-apply the same rule about which status changes are allowed. Whichever of the two arrives second is refused, and the admin sees that the investment is already completed or already cancelled rather than silently paying a second time.
A settled investment told the customer nothing when its plan had been deleted
Deleting a plan hides it rather than removing it, and the add-on deliberately still settles the investments that deletion leaves behind. But the completion email read the hidden plan's name, so it failed before it could be queued — and because the email and the in-app notification were handled together with the email going first, the notification was never reached either. The settlement itself was correct and the money moved. The customer simply never heard about it, and the only trace was an error naming a missing title.
- Fixed the email and the in-app notification now stand on their own, so a failure to send the email can no longer take the notification down with it, and each failure is logged for what it is.
- Changed where the plan or the term behind an investment can no longer be read, the completion email now goes out with a generic plan name and no term, instead of not going out at all. The investment does not keep a copy of the plan's name, so there is nothing more specific to put there — and a settlement notice that says a little less is better than silence about money that moved.
The settlement job logged a database state instead of what went wrong
When anything went wrong part-way through settling a matured investment, the job's error handler began by unwinding work that may already have been committed, or already unwound. That step then failed on its own and escaped before the real error was ever written down, so what an operator read was a database transaction state rather than the reason a settlement had not gone through — on a run whose work may in fact have completed. Nothing was written incorrectly; what was lost was the ability to find out why.
- Fixed the job's error handler no longer trips over its own unwinding step, so the failure an operator reads is the real cause of the settlement problem, including on a run that had already committed its work and needed no intervention at all.