The short version, before you move a shop here: the L$ of a sale never pass through Plurion, your data leaves with you the day you ask, and every figure on this page is counted from the code each time the page is built.
There is a lot here, and some of it is technical — it is written for anyone who wants to see how the thing actually works. If something on this page concerns you, ask us to explain it. That is a normal thing to want, and we can.
Every number here is recounted from the source when the page is built.
The buyer pays your vendor and Second Life credits you. Plurion is never in the middle: there is no balance of yours for us to hold, and nothing of yours for us to lose.
On the free plan our 5% is one of those splits, sent by your vendor like any other — not deducted from a balance we hold. We hold no balance, not even for ourselves.
Store credit — what a shop grants its own buyers, kept as a ledger. Movements are added, never rewritten.
Store credit is checked, debited and delivered as one movement — never charged twice, never charged without delivery. Three checks make that true, and the order is the guarantee.
Asked before anything else. A buyer you banned is stopped here — not after the money moved.
Stock present in a live box, product still sellable.
And the amount is the one the server recomputed itself, not the one it was handed.
A double click, a network retry, two racing tabs all land on the same result: debited once.
The debit and the delivery are written together — either both, or neither.
An in-world sale is simpler still — the L$ never enter this path at all. These checks exist for the one balance that does: store credit.
Every object you rez and every row you own carries your shop with it.
A vendor, a delivery box, a visitor counter registers once, receives its own secret, and signs every call it makes after that.
Thirteen separate gatekeepers: one per family of in-world object, plus one each for merchant and customer sessions. A vendor can only ever speak for itself — never for another one, and never for your shop.
Every single way the system reads data carries your shop identifier inside the query. It is not a setting someone can forget to tick: it is part of how the data is asked for.
Thirteen tests do nothing but attempt to read another shop's data.
Nothing about what you earn is public. Where Plurion shows a merchant on its public network, it shows a rank, never an amount.
A shop that opts out is filtered on the server, before the response is built — no name, no region, no activity. Not a flag on a payload that still carries the data.
Nobody signs in as you, because there is almost nothing to sign in with. The risk that actually costs a merchant their shop is not an exploit, it is someone convincing them to hand over a password — so here is what Plurion will never ask you for.
Anything that does either one is not us. That is the whole test — you do not need to understand how any of this works to apply it.
You were never asked for one. There is no field anywhere that stores one, and nothing in the system can send one.
So anything reaching your inbox in Plurion's name did not come from Plurion — and you can check that yourself: you never gave us an address.
No Plurion object in Second Life has anywhere to type a password at all.
One that asks you for yours is not ours.
Merchant and customer each have their own cookie, out of reach of the page's JavaScript. Every change additionally requires an anti-forgery token, so a request forged from another site does nothing.
An access link handed to a customer in-world is exchanged for a session and dies on first use.
A window you can land anywhere inside, down to the second.
Every write is recorded continuously, so a restore lands on any second in the last six hours — not on last night's snapshot, on the second before the mistake. Putting the service back onto a restored database was measured at three to six minutes in a drill run end to end.
A procedure that gets invented during an incident is a procedure nobody has read.
A delivery that fails is retried eight times, over a widening interval — and it stays visible to you rather than being dropped quietly.
The measure of a service you can trust is what happens on the day you decide to stop using it.
Export whenever you want. Ask for deletion and, after a 30-day grace period you can cancel, every identifying detail is stripped across the system — names and avatar keys erased, messages and visitor history deleted.
Security is what protects the system. Privacy is what is kept, for how long, and what is left once you ask for it to go. Two questions, two pages — with the durations the system actually uses.
Read Privacy →A page that only lists what a service cannot do is telling you half the story. Here is the other half — the three things that are genuinely in our hands.
Your shop keeps selling, keeps delivering and keeps its data. It moves to the free plan, which takes 5% of sales instead of a monthly fee. There is no cut-off, no grace countdown and nothing to rescue.
In case of abuse or a security problem we suspend first and explain after — vendors stop selling, deliveries stop. It is the one situation where we act without telling you first, and the only one that genuinely switches a shop off.
In any other case we tell you before ending the service, and you leave with your data. The terms say it in the same words.
Everything above, unabridged. Nobody has to read this — it is here so that the person who wants to check can.
Thirty-nine suites run against a real throwaway database, created for the run and deleted after it.
The rest of the suite runs on every push. A boundary that breaks is a red build, not a discovery three weeks later.
Production dependencies are audited every week and on every dependency change; a single high-severity advisory turns that check red.
31 lines·6 families·Recounted at every build·None of it is required reading
Every door into an account, and what holds each one shut.
Five failed attempts, then the account locks for fifteen minutes. The counter follows the avatar, not the address: spreading the attempt across machines does not get around it. A correct guess does not reset it either. A second limit applies per address, ten a minute. Passwords are PBKDF2-SHA-512 at 100,000 iterations — the platform ceiling — with a per-account salt.
The code is never stored in the clear, only its digest. Ten-minute life, five attempts.
A link handed over in-world is exchanged for a session and dies on first use.
Every link is exchanged for a session and revoked on first use. A bulk revocation exists.
Cookies are HttpOnly and Secure — no script on the page can read them. Two distinct cookies, merchant and customer, never mixed.
An anti-forgery token is required on every mutation, merchant side and customer side alike: redelivery, spending credit, opening a ticket.
Being inside is not the same as being allowed. Your role, your shop and your own orders are separate walls, and each one is checked on the server.
Roles are checked per route, on the server, never by hiding a button. Only an owner or an admin can touch the team. Nobody can grant the owner role, and no one can promote or remove themselves. A removed member loses access on their next request, not at their next login. Seventy-three tests cover the role cascade and the team routes alone.
Every data-access method carries the shop identifier in its query. Nine tests do nothing else, plus four on the delivery callback, plus a suite that runs against a real throwaway database. The same boundary is asserted again across the route tests — it is checked in every route, not in one place.
Every order is bound to the customer who made it. A transaction identifier belonging to another customer of the same shop returns not found, and the listing endpoint refuses any product the caller does not own. The shop boundary and the customer boundary are two different walls.
Every in-world object signs what it sends. Here is what that signature covers.
Every call is signed and must arrive within five minutes of its timestamp. Polls, heartbeats and syncs, harmless to repeat, stop there; every other call also carries a single-use token, refused the second time.
The SHA-256 digest of the body is part of the signed chain: change one byte and the signature no longer matches.
Thirty-two random bytes, shown again only to the shop owner and rotatable from your settings — objects linked by touch no longer use it.
Product and recipient are read back from the transaction, never from the link: a redelivery URL rewritten with someone else’s name still delivers to the person who paid. Holding a customer’s session is not enough to redirect their delivery.
The credit ledger is the only balance in the system. These are the ways that balance is held.
Idempotency covers the whole operation, not just the debit: a double click debits once.
Deliverability is checked before the debit: stock present in a live box, product still sellable.
The ban applies before any mutation, and the money path enforces the same level.
The credited shop is the one the terminal belongs to, resolved on the server. A shop identifier sent in the request body is never read.
The server recomputes the amount from its own records — base price, sale, promo — and compares. Paying less returns an error and creates no transaction at all, rather than a sale at the wrong price; paying more sells at the right price and sends the difference back. The one tolerance is a sale's own price, honoured for three minutes after it ends — the time vendors take to learn it ended.
A fixed-amount discount is clamped to the gross price: the net can reach zero and never goes below. A discount cannot turn into a payment.
A redelivery that fails terminally on an already-delivered purchase does not credit the buyer back. What was actually delivered decides, not what the queue last reported.
Two worker runs in parallel never claim the same job. The claim is atomic: the loser is handed nothing to do, rather than a second copy to send.
The layer below your shop — the service itself, which never touches an account.
The backend calls out to your in-world objects, whose address must match the shape of a Second Life region URL — an allow-list, not a block-list — and to browser push services, which must be public https addresses. Both are checked on the parsed URL, not on the string. A push to a vendor is checked again at the moment of the call, and redirects are refused: a destination that answers “go there instead” is a failed push, not a new target.
Parameterised templates across the whole access layer — a value is never glued into a query string. Counted again at every build; today, 794 parameterised queries and no concatenated one.
Content policy, refusal to be framed, encrypted transport forced for two years, content type pinned.
Capped at the edge on api.plurion.io, before it reaches the service.
Being refused is not the only thing that counts. What a refusal tells you counts too — a merchant fears having their numbers guessed as much as stolen.
The code request answers identically for a known and an unknown name, and the sixty-second cooldown applies to both. The response does not say which avatars exist here.
Opting out is applied on the server, before the response is built: no name, no region, no activity. Not a flag on a payload that still carries the data.
Grid figures are aggregated across every shop. No per-shop number enters the payload, so none can be subtracted back out of it.
A cross-shop request returns not found with null fields — the same answer as a resource that never existed. Existence itself is not disclosed.
Malformed, empty and random input are refused cleanly, never with a server error. A duplicate signup answers with a conflict, not an internal failure carrying the database’s own words.
The kiosk lookup returns an identifier and a name. Plan and remaining days are not in the response to be found.
Security work that gets someone threatened is security work that stops being reported. So the terms of reporting are written down in advance.
Report a vulnerability →Join the Plurion Discord for help, updates,
and direct answers from the team.