1Where it stands
One module built and tested. The two hardest pieces are still unstarted.
at10bucks runs today on a third-party platform hosted with an ISP where there is no server access, where sendmail is broken — so it cannot send order confirmations, notifications or password resets — and where it continues to grow unsupervised. It has previously been held to ransom by a vendor's employee. Two earlier versions failed and members kept arriving anyway, which is a stronger signal than any feature.
The move to NanoReash is about owning the stack. Nothing in this report depends on the current platform's source; the schema and behaviour were reconstructed from your own database export, your admin screens and the 2012 archive.
2Decisions taken
Settled during this work. Recorded so they are not re-litigated.
Commission
3% of the job, minimum $1.00, maximum $10.00. The thresholds fall at $33.33 and $333.33 because they fall out of the rate rather than being chosen — which is where 3 / 33 / 333 comes from. The cap is $10 because that is the brand.
The cap is not a flat fee. A flat $10 on a $10 job would leave the seller nothing. The commission is 3%, bounded at both ends. This was misread once during design and is stated plainly here for that reason.
| Order | Commission | Governed by | Processing | Seller receives |
|---|---|---|---|---|
| $10.00 | $1.00 | floor | $0.48 | $8.52 |
| $33.33 | $1.00 | rate | $0.88 | $31.45 |
| $55.00 | $1.65 | rate | $1.26 | $52.09 |
| $420.00 | $10.00 | cap | $7.65 | $402.35 |
| $5,000.00 | $10.00 | cap | $87.80 | $4,902.20 |
Commission and payment processing both come off the seller's payout. The buyer always pays the listed price, because the price is the brand. The seller sees one combined figure before accepting, not at payout. The commission and processing split is stored for reconciliation but never displayed.
Commission applies to the ex-tax value, and never to the vendor toll — out-of-pocket expenses are cost recovery, not the seller's earnings.
Money and tenancy
- at10 never holds money. A licensed provider holds funds and carries the licence; at10 works out the split and instructs. Sellers onboard with the provider directly. PayPal Adaptive is dead.
- at10 is one NanoReash tenant (
lang). Sellers are members inside it, not tenants. Rate, floor and cap are stored per tenant — never global, or a second marketplace inherits at10's rate. - One database. Listings hang off the CMS page row and sellers are rows in
reash_users; splitting the databases would make both a cross-schema join with no transaction across them. - Documents are InvoiSys's job. at10 calls InvoiSys; it never implements invoicing.
Marketing copy
“$10 − 7.7% = $9.23” does not survive the floor or processing — the real figure is $8.52. Retired. The replacement is the schedule itself: 3% of the job, minimum $1, never more than $10. True at every price point, no footnote.
Reviews
Ratings are per completed order, with a mandatory written reason. Completed order count is the primary signal; the average is suppressed below five ratings and there is no leaderboard. Wording describes the delivery (“not what I expected”) rather than the person (“Very Poor”). Neither side sees the other's rating until both have submitted or the window closes.
3What is built
Module v1.3. Linted, executed, and verified against a real database — not just written.
| Component | State | Notes |
|---|---|---|
| Commission calculation | Done | Pure, integer cents, boundaries self-tested |
| Per-tenant rule storage | Done | JSON per lang, append-only, effective_from |
| Transaction stamp | Done | Never recomputed; rate, floor, cap and tax rate stored with it |
| Seller fee disclosure | Done | Shown before accept, one combined figure |
| Listing schema | Done | 3 tables, InnoDB / utf8mb4 |
| Listing library | Done | Create, edit, extras, quote; ownership gated |
| Member panel | Partial | 8 tabs; My Jobs wired, others honestly empty |
| Admin commission screen | Done | Rule in force, history, worked examples |
| Orders / state machine | Not started | The real work |
| Two-sided ledger | Not started | Belongs in InvoiSys, not at10 |
| Escrow / withdrawals | Not started | Provider not yet chosen |
| Disputes | Not started | Exists in live data; absent from the plan until now |
Package layout
.htinc/at10.inc router nano_apps/at10/nano_app.json manifest (version must match core) nano_apps/at10/lib/at10_core.php settings, calc, stamp, disclosure nano_apps/at10/lib/at10_listing.php listings, extras, order quote nano_apps/at10/lib/at10_panel.php member panel nano_apps/at10/css/at10_panel.css panel stylesheet (as supplied) nano_apps/at10/schema/*.sql 3 tables, applied by hand nano_apps/at10/data/.htaccess deny direct web access INVOISYS_PATCH_money_helpers.php paste into invoisys_core.php, then delete at10_bump_version.php release bump, refuses on version drift
Engineering rules applied
- Integer cents throughout. No float ever holds a monetary value.
invoisys_cents()is a direct port oftoCentsfrom the wizard — deliberately the same formula, because PHP'sround()and JavaScript'sMath.round()disagree on negative halves. - One definition. Processing rate, tab list, listing states and the percent-to-fraction conversion each exist in exactly one place.
- Client-side is display, never authority. Quotes take extra IDs and look up prices; a price from the browser is a price the buyer can edit.
- Gated at the button and the function. Every write re-checks; the router checks again before rendering a form.
- Fails to zero. An unconfigured tenant charges nothing rather than inheriting at10's rate.
Bugs found by running it
Wrong data directory. Settings resolved through invoisys_base_dir(), which would have filed at10's commission rules inside InvoiSys's storage — outside at10's own .htaccess, carried by InvoiSys backups, destroyed by InvoiSys's Clear All Data.
mb_substr() on a host without mbstring. Would fatal at the moment a seller saves an extra. Core already solved this with invoisys_safe_truncate().
mysqli throws by default on PHP 8. A database blip raised out of the DB handle and white-screened the entire member panel — every tab gone because one section could not load. Now caught.
Unconditional require of InvoiSys core. Fatalled when core was already loaded or sat at a different path.
None of these were visible by reading. All four came from execution.
Performance, measured
500,007 listings across 50,000 sellers, 68.6 MB:
My Jobs (one seller) 0.364 ms Browse active, 20 rows 0.310 ms One listing by page_id 0.084 ms Extras for a listing 0.135 ms baseline SELECT 1 0.021 ms
Adding tables costs the rest of the database nothing — MySQL does not scan tables it was not asked about. Under heavy load the web tier and connection limits fail long before these queries do.
4The existing data
Read from the structure-only export. 44 tables, no rows shipped.
at10 and 19 prefixed at10_, both with a full marketplace set — two sets of orders, transactions, withdrawals and ratings. Which is live must be settled before anything is migrated. If both hold real orders, that is two ledgers to reconcile.Problems already visible
| Issue | Where | Consequence |
|---|---|---|
Money as varchar(255) |
orders, transactions | Values like '10.00 ' or '' are possible |
Money as double |
withdrawals, admin earnings | Float drift in stored amounts |
pid tinyint(4) |
admin_earnings | Tops out at 127 — product ids above that are wrong already, and unrecoverable |
| No status column | orders | State is five flags plus a cancellation subsystem; contradictory rows are expressible |
| MyISAM, latin1 | every job_* table |
No transactions on money tables; real mojibake risk |
0000-00-00 |
users.user_registered | Rejected by strict mode on MySQL 8.5 |
Ids as 1.23E+29, 10Bucks |
balances | Some identities cannot be matched at all |
| Three widths for one identity | uid columns | bigint unsigned, signed bigint, int(11) |
What the archive showed
- Price is variable. $10 is a base — up to ten extras at arbitrary prices, plus a vendor toll. The bounded 3% was the right model after all.
- Two more revenue streams the plan lacked: a $1 listing fee on approval and $10 to feature. Both are at10 selling to a member, not a split — a different money path, and the only place at10 has its own tax exposure.
- Geo is real and populated. Country / state / city with a distance radius, and Shoalhaven down to 68 suburbs. The founding local idea is data, not a hypothesis.
- Sellers are global — Nepal, Sri Lanka, Pakistan, Malaysia, US. Provider payout coverage must be checked against where members actually are.
- A definition had already drifted: admin says Closed, member screens say Cancelled. Settled as Cancelled.
5Risks
Ordered by what it costs to be wrong.
| Risk | Level | Position |
|---|---|---|
| Member data sits on a competitor's stack with no server access | High | The only irreversible item. Structure received; the full export must be held independently. |
| Lost-and-found upload handler executes uploaded PHP | High | Live remote-code-execution path on a server you do control. Five lines to fix. |
| Chargebacks against a capped fee | High | A $2,000 order earns $10 and carries full reversal exposure. Who absorbs it is undecided. |
| Auto-complete moves money on a timer | Medium | Harmless with emulated balances; irreversible once a provider holds funds. |
| Provider cannot pay some seller countries | Medium | Could narrow the provider choice to one, or none. |
| Infringing and fake-engagement listings | Medium | Present in the live data. Providers terminate accounts over this; DMCA lands on whoever hosts the file — after migration, you. |
| Members re-onboarding after a password reset | Medium | Hashes will not transfer. Addresses date from 2012; email must send from a server you control. |
| Scope growth | Medium | The 11-tab panel adds a reverse marketplace with a matching engine before orders exist. |
| Licence position on the current platform | Low | Nothing built derives from it. Schema and behaviour came from your own data. |
6Open questions
- Which table prefix is the live one — and does the other hold real orders?
langisint(3)on the CMS page table andvarchar(5)onreash_users. One key, two types. Which is canonical?- Where the ledger lives: append-only JSONL like InvoiSys documents, SQL, or JSONL with a SQL mirror. The export's row counts should decide it.
- Chargeback liability — provider, seller, or at10.
- Provider selection, and payout coverage for seller countries.
- Whether location matching returns as a first-class feature. The data supports it.
- Confirming a payout email before first payout — no field records that confirmation yet.
- Order state machine: mapping five legacy flags onto canonical states, including contradictory rows.
7What to do next
In this order, and the first two are not development work.
1 — Take the export
Everything else in this project can be rebuilt. Member data on a server you cannot reach cannot. Pull the full dump, keep it somewhere independent of that ISP. The structure has been read; the data has not been secured.
2 — Close the lost-and-found upload hole
It accepts a .php file and serves it back executable, with no .htaccess anywhere in that archive. On a server you control.
3 — Settle the two questions that block design
Which prefix is live, and how many transactions exist. Those decide the ledger's storage and the migration's shape. Both are single queries against the dump.
4 — Then the order state machine
It is the piece everything else hangs off, and the only place the legacy data actively fights you. Commission has nowhere to write until orders exist.