Consigna Manual, as shipped in the download
Consigna — User Manual
A consignment shop's items, sales, splits and payouts. Version 3.1.4 [src: app/controllers/api.php:128].
About this manual
Every statement here was written by reading Consigna's own source, and each one carries the file it came from in a bracketed src marker. Paths are relative to the folder this docs directory sits in. If a sentence disagrees with the application, the application is right and this manual has a bug — the markers exist so you can check rather than take our word for it.
Nothing is described that the code does not do. Where something is deliberately limited, that is said plainly rather than left out.
What Consigna is
People leave goods, the shop sells them and keeps a share [src: app/controllers/mcp.php:55]. The engine that divides the money is what the source calls the moat: money correctness is everything [src: app/src/Consign.php:3].
The money, and why it cannot drift
All money is integer cents. All splits are integer basis points, where 10,000 is 100%. Floats never touch a stored or computed amount [src: app/src/Consign.php:5].
The consignor's share is computed as intdiv(sale × bp + 5000, 10000) — round half up, integers only — and the shop's share is the remainder [src: app/src/Consign.php:42].
That last detail is the whole trick. Because the shop gets what is left rather than a second rounded calculation, the two shares always sum exactly to the sale price. The source states the consequence: every rounding penny lands in exactly one pocket, never lost, never duplicated [src: app/src/Consign.php:10].
A product that rounded both halves separately would, on odd amounts, either invent a penny or lose one. This one cannot.
The split is snapshotted onto the sale
The basis points and both shares are written onto the sale row at the moment of sale [src: app/src/Consign.php:203], and the source is explicit about why: later split changes never rewrite history [src: app/src/Consign.php:14].
Renegotiate a consignor's terms and past sales keep the terms they were made under.
Which split applies
An item's own override where one is set, otherwise the consignor's default [src: app/src/Consign.php:49], clamped to the 0–10,000 range.
Selling an item
Only an available item can be sold, and the refusal names the actual state [src: app/src/Consign.php:173] — already sold, returned to the consignor, donated, or expired, with expired telling you to set it back to available first.
The sale is atomic. The flip from available to sold is a conditional update inside a transaction, so if the update matches no rows another request got there first and the answer is a refusal rather than a second sale [src: app/src/Consign.php:193].
A negative sale price is refused [src: app/src/Consign.php:182], as is an invalid date.
Undoing a sale
An undo deletes the sale and puts the item back on the floor, in one transaction [src: app/src/Consign.php:229].
It is refused when the consignor has already been paid against it — specifically, when removing that sale would take their balance below zero [src: app/src/Consign.php:226].
That is the guard that keeps the ledger honest. Without it, undoing a sale after paying somebody would leave the shop having paid out money the books no longer say was owed.
Payouts
A payout can never exceed the consignor's current balance [src: app/src/Consign.php:242], and the refusal tells you what is actually available [src: app/src/Consign.php:259]. A zero or negative amount is refused [src: app/src/Consign.php:251].
The balance is the sum of consignor shares on their sold items minus the sum of their payouts [src: app/src/Consign.php:16] — derived, not stored, so it cannot disagree with the sales and payouts it is made of.
The check happens inside the transaction that writes the payout [src: app/src/Consign.php:254], so two payouts racing each other cannot both pass a balance check that only one of them should.
Item lifecycle
available --sale--> sold --undo--> available
available <--set-status--> returned / donated / expired
[src: app/src/Consign.php:19]
Five statuses [src: app/src/Consign.php:26], of which four can be set directly — sold is reachable only by recording a sale [src: app/src/Consign.php:28], and a sold item's status is locked until the sale is undone [src: app/src/Consign.php:275].
The consignor portal
A consignor can be issued a token link and have it revoked [src: app/index.php:81]. The token is the credential on a public route [src: app/index.php:138], and the consignor can pull their own statement as a PDF [src: app/index.php:137].
Telling consignors by email
Two switches under Settings → Write to the consignor, both off on a fresh install and both sent only through your own SMTP server, to consignors with an email address on file [src: app/controllers/api.php:37]:
- when one of their items sells — the item, the date, the price, their share and their balance with you [src: app/controllers/api.php:81];
- when a payout to them is recorded — the amount, the date, the method and their remaining balance [src: app/controllers/api.php:113].
A mail server that refuses the message never undoes the sale or the payout. A sale recorded by an AI agent sends the same notes and fires the same webhook as one recorded on screen or through the API.
Users and roles
Three roles [src: app/controllers/v3.php:27]. The source names the two things that stay with the owner and gives one reason covering both — they are the consignor's contract and the consignor's money [src: app/controllers/v3.php:20]:
payout.record, because a payout is cash leaving the till against someone else's balance [src: app/controllers/v3.php:22].consignor.edit, because the split is the agreement, and changing it silently re-prices every future sale for that person [src: app/controllers/v3.php:23].
Deleting is admin-only for the same kind of reason: a sale row is what a settlement is computed from [src: app/controllers/v3.php:25].
| Permission | viewer | member | admin |
|---|---|---|---|
.view permissions | yes | yes | yes |
audit.view | yes | yes | yes |
item.edit | — | yes | yes |
sale.record | — | yes | yes |
portal.issue | — | yes | yes |
payout.record | — | — | yes |
consignor.edit | — | — | yes |
| deletion, settings, team | — | — | yes |
The shop floor takes items in, puts them out and records a sale [src: app/controllers/v3.php:19]. It does not pay anybody or change anybody's terms.
The audit trail is not the viewer's
The viewer's grants are listed one by one — consignors, items, payouts and sales [src: app/controllers/v3.php:32] — so the audit trail is not among them. Before 3.1.4 the viewer held the wildcard *.view, which matched audit.view as well.
An API key carries its holder's role at the REST door as it does at the agent door: adding an item needs item.edit, recording a sale sale.record, and recording a payout payout.record, which only an administrator holds [src: app/controllers/api.php:225]. Before 3.1.4 the REST writes checked only the key's read/write scope.
Backups follow the model
Consigna's database backup downloads are permission-gated, requiring the settings permission [src: app/controllers/api.php:422], as are the restore page and the scheduled-backup token. A viewer cannot download the database.
The API and agent access
Five tools are exposed to an agent, of which one writes [src: app/controllers/mcp.php:62]: consignors, consignor detail, items and a settlement preview on the read side; recording a sale on the write side.
An agent cannot record a payout, and the instructions give the reason in one line: paying a consignor is cash leaving the till, and it stays with the shop [src: app/controllers/mcp.php:60].
The instructions also hand an agent the exact arithmetic — intdiv(sale*bp + 5000, 10000), round half up, integers only, the two shares always summing to the sale price with no penny lost or invented [src: app/controllers/mcp.php:57]. An automation reconciling the books can therefore reproduce the figures rather than approximating them.
What Consigna does not do
It does not let an agent pay anybody [src: app/controllers/mcp.php:60].
It does not move money. A payout is a record that cash left the till; the cash leaves by whatever means you already use.
It does not lose or invent a penny [src: app/src/Consign.php:10], and it does not let a split change rewrite a past sale [src: app/src/Consign.php:14].
It does not let a sale be undone after the consignor has been paid for it [src: app/src/Consign.php:226].
It does not let the shop floor change a consignor's terms [src: app/controllers/v3.php:23], because the split is the agreement.