OmniStock

51 screens · custody ledger for 3PL warehousing

Every screen is annotated with the specification requirement it has to make visible. A screen that carries nothing got cut. Built in plain HTML and CSS against the design system — no framework, no build step.

A · Auth & scope

Device credential and operator credential are separate, because a picker cannot type a password 200 times a shift and devices are shared from a charging rack.

C · Catalog & locations

Reserved accounts are shown as real locations, because that is what they are — every unit is always somewhere, including the missing ones.

E · Counting & variance

Two operators counting the same bin both post. The system does not pick a winner.

H · Client portal

A separate shell. No site layout, no bin paths, no operator names, no write control — structurally, not by hiding.

OmniStock

Sign in

Office access. Floor operators sign in on a handheld with a badge or PIN.

Enterprise tenants use SSO — you will be redirected.
Sessions last 10 minutes and refresh silently. A lost device is revocable within one window.
OmniStock
Device TC-52-014Enrolled

Who is on shift?

The device is already trusted. This identifies you — every movement you post is stamped with your operator ID, never the terminal's.

Start shift
Device credential and operator credential are separate. "Device TC-52-014 posted this" is not an attribution.
OmniStock

Choose your scope

You hold goods for four clients across two sites. Scope is set before any data loads — nothing outside it is queryable, not just hidden.

OmniStock
LockedShift still open

Screen locked after 15 minutes

Your shift is still running and nothing has been lost. 3 movements are queued on this device and will post when you unlock.

Unlock End shift and sign out
Tuesday · shift 2 · 14:26

42 operators on the floor

Everything below is derived from the movement ledger. Nothing on this page is a stored figure that someone typed.

Post movement
Movements today38,204 +6.2% vs last Tuesday
Open variances412 12 above disposition threshold
Quarantined27 oldest 3h 12m
Devices offline6 64 writes queued

Movement throughput

00:0008:00 16:0023:00 3,120 peak
Reserved scan-write floor holding — no 429 issued today p99 112ms

Variance queue — ranked by exposure

Open triage
ItemOwnerUnitsExposureAgeGate
29944-HAldgate Supply Co−472£5,2863h2nd approver
44102-TKestrel Foods−240£1,0081d2nd approver
88213-KKestrel Foods−12£21423mController
55810-QAldgate Supply Co+8£1124hController
Ranked by extended value × contractual SLA weight — not by recency 412 total

Quarantine

Review
27 movements accepted but
not yet reconciled

Each one is a real physical action that failed validation on reconnect. They were quarantined, not rejected — discarding them would destroy the only evidence the action happened.

Devices

All 48
TC-52-014 Synced
TC-52-031 Offline · 38
TC-52-007 Offline · 61
TC-52-044 Clock skew 41m
Cold room and trailer dead zones are ordinary

Owners

Kestrel Foods184,220
Northvale Ltd71,904
Aldgate Supply Co29,118
Penrose Group11,662
Units held under custodyManage

Command palette

Press ⌘K anywhere. At 500k+ SKUs across four owners, navigation by clicking through a tree stops working — search is the primary way in.

Alerts

Operational signals that need a person. Not a feed.

Catalog

Items scoped to (tenant, owner). Quantities shown here are derived balances — this table has no editable quantity, at any privilege level.

New item
Owner: Kestrel Foods Site: SITE-4 Status: Active
1,284 items · 14 columns
Item catalog, 14 columns. Quantities are derived balances and are not editable.
SKU Description Owner UoM Class On hand Reserved Available Primary bin Lots Min Status Last movement Doc
88213-K Ambient pallet wrap, 500mm × 300m Kestrel FoodsEAAmbient 1,8471201,727 SITE-4/A/12/032400 In stock 2026-08-19 14:03 CS-8812
88214-M Chilled tray liner, 400 × 600 Kestrel FoodsCSChilled 21220012 SITE-4/C/02/111250 Below min 2026-08-19 13:58 PCK-88301
90551-B Corrugated shipper, single wall Northvale LtdEAAmbient 000 SITE-4/A/04/1801,000 Stockout 2026-08-19 13:40 TTL-00088
73390-X Frozen carton, 12 × 400g Kestrel FoodsCSFrozen 4,0965123,584 SITE-4/F/01/027800 In stock 2026-08-19 14:01 RCV-44214
61027-D Returnable dolly, blue Northvale LtdEAEquipment 3180318 SITE-4/Y/00/01050 In transit 2026-08-19 13:51 TRF-10233
55810-Q Shrink sleeve, 65mm lay-flat Aldgate Supply CoRLAmbient 76076 SITE-4/B/09/072100 Below min 2026-08-18 16:30 ADJ-00918
44102-T Thermal label roll, 100 × 150 Kestrel FoodsRLAmbient 12,4801,20011,280 SITE-4/A/01/0142,000 In stock 2026-08-19 13:44 PUT-71121
29944-H Desiccant sachet, 5g Aldgate Supply CoEAAmbient 000 VARIANCE:aldgate1500 Variance 2026-08-19 13:47 DMG-00412

88213-K

In stock

Ambient pallet wrap, 500mm × 300m · Kestrel Foods · There is no edit control for quantity on this page. There is no such control anywhere.

On hand1,847 3 bins · 18 more in other accounts
Reserved120 2 open orders
Available1,727 on hand − reserved
Ledger depth9,412 movements, all replayable
PositionLotOwnerOn handReservedAvailableLast touched
SITE-4/A/12/03LOT/2026-0114Kestrel Foods 1,2041201,0842026-08-19 14:03
SITE-4/A/12/04LOT/2026-0114Kestrel Foods 43104312026-08-19 11:02
SITE-4/A/12/09LOT/2026-0088Kestrel Foods 21202122026-08-17 08:41
PENDING:site-4LOT/2026-0114Kestrel Foods 6002026-08-19 13:55
VARIANCE:kestrelLOT/2026-0114Kestrel Foods 12002026-08-19 14:03

PENDING:site-4 holds 6 units posted offline that failed validation on reconnect. They are quarantined, not rejected — the physical action already happened.

SeqRecordedFromToQtyReasonActorDocHash
10004122026-08-19 14:03:11 A/12/03VARIANCE:kestrel 12COUNT_SHORTop-4471 CS-88129f3a…c1f2
10003982026-08-19 13:58:02 EXTERNAL:acmeA/12/03 600RECEIPTop-2210 RCV-441927b21…8e31
10003552026-08-19 11:02:44 A/12/03A/12/04 431PUTAWAYop-2210 PUT-711204c88…a07f
10003412026-08-19 09:15:20 A/12/03EXTERNAL:cust-8871 240PICKop-1180 PCK-88301e019…3d55
LotOwnerExpiryOn handPositionsStatus
LOT/2026-0114Kestrel Foods2027-01-14 1,6352Good
LOT/2026-0088Kestrel Foods2026-10-02 2121Expiring
SKU
88213-K
GTIN
05012345678900
Owner
Kestrel Foods
Unit of measure
EA — each
Handling class
Ambient
Dimensions
500 × 300 × 300 mm
Gross weight
14.200 kg
Min level
400 — configurable per owner
Created
2025-03-11 by admin-004

Edit item · 88213-K

Catalog fields only.

Identity

Immutable. Merging duplicates posts a RECLASSIFY movement set.
Changing owner requires a title transfer, not an edit.

Physical

A reorder trigger, not a stock value.
Cancel

Balances

Stock on hand by (owner, item, location, lot) — the projection. A cache of the ledger. If the two ever disagree, the ledger wins and this table is rebuilt.

Site: SITE-4Non-zero only
Last projected 14:26:03 · snapshot 04:00 · 88213-K: 1,204+431+212 = 1,847 in bins
OwnerItemPositionLotOn handReservedAvailableLevel
Kestrel Foods88213-KSITE-4/A/12/03LOT/2026-0114 1,2041201,084 1,204ok
Kestrel Foods88213-KSITE-4/A/12/04LOT/2026-0114 4310431 431ok
Kestrel Foods88213-KSITE-4/A/12/09LOT/2026-0088 2120212 212ok
Kestrel Foods88213-KVARIANCE:kestrelLOT/2026-0114 1200 12variance
Kestrel Foods73390-XSITE-4/F/01/02LOT/2026-0201 4,0965123,584 4,096ok
Kestrel Foods88214-MSITE-4/C/02/11LOT/2026-0177 21220012 212below min
Northvale Ltd90551-BSITE-4/A/04/18 000 0stockout
Northvale Ltd61027-DSITE-4/Y/00/01 3180318 318in transit
Aldgate Supply Co29944-HVARIANCE:aldgateLOT/2025-9911 47200 472variance
Kestrel Foods88213-KPENDING:site-4LOT/2026-0114 600 6pending

The last two rows are units that are not in a bin. They are still somewhere — that is the point. "Unaccounted for" is never an answer this system can give.

Locations

site > zone > aisle > rack > bay > bin — plus the reserved accounts, which are real locations, not statuses.

Physical

4,812 bins
  • SITE-4Tilbury DC
    • AAmbient1,840 bins
    • CChilled602 bins
    • FFrozen318 bins
    • YYard44 bays

Reserved accounts

These behave exactly like bins in the ledger. Every movement has a from and a to, so supply, shipment, loss and damage all need an address — which is what makes conservation a structural property rather than a check.

AccountPurposeNegative
EXTERNAL:{party}Supplier receipts and customer shipmentsAllowed
VARIANCE:{owner}Count discrepancies awaiting dispositionAllowed
DAMAGE:{owner}Written-off units, still attributableAllowed
PENDING:{site}Quarantined offline postsAllowed
WIP:{owner}Reserved for kitting. Unused in v1.Allowed
Any physical binRacking, floor, yardBlocked

A movement that would drive a physical bin negative aborts at commit with OS003 negative_position, and the API returns 409 with the current position so the operator can be shown what is actually there.

Lots & serials

Custody travels with the lot, not with the bin — owner_id is carried here, which is why moving a pallet never silently moves ownership.

LotItemOwnerReceivedExpiryOn handPositionsStatus
LOT/2026-011488213-KKestrel Foods2026-01-142027-01-141,6352Good
LOT/2026-020173390-XKestrel Foods2026-02-012026-12-014,0961Good
LOT/2026-008888213-KKestrel Foods2026-03-292026-10-022121Expiring 44d
LOT/2026-017788214-MKestrel Foods2026-06-112026-09-112121Expiring 23d
LOT/2025-991129944-HAldgate Supply Co2025-11-022026-08-024721Expired
SER/TC-52-01461027-DNorthvale Ltd2024-08-1911Serialised

Movement ledger

Append-only, hash-chained, partitioned monthly. 292M rows a year at current volume. No row on this page has an edit or delete action, at any privilege level.

Post movement
TodayAll ownersSITE-4
38,204 today · chain verified to seq 1,000,412
SeqRecordedItemFromToQtyReasonActorDeviceDocState
100041214:03:1188213-K A/12/03VARIANCE:kestrel 12COUNT_SHORTop-4471TC-52-014 CS-8812Posted
100041114:01:5273390-X EXTERNAL:acmeF/01/02 1,200RECEIPTop-2210TC-52-009 RCV-44214Posted
100041013:58:4088214-M C/02/11EXTERNAL:cust-8871 200PICKop-1180TC-52-022 PCK-88301Posted
100040913:55:0288213-K A/12/03PENDING:site-4 6QUARANTINEop-4471TC-52-014 QRN-0091Quarantined
100040813:51:1961027-D SITE-9/Y/00/04SITE-4/Y/00/01 318TRANSFERop-3302TC-52-031 TRF-10233In transit
100040713:47:3329944-H B/09/07DAMAGE:aldgate 24DAMAGEop-1180TC-52-022 DMG-00412Posted
100040613:44:0744102-T A/01/01A/01/02 2,400PUTAWAYop-2210TC-52-009 PUT-71121Posted
100040513:40:5590551-B A/04/18A/04/18 640TITLE_XFERadm-0004 TTL-00088Paired

seq 1,000,412

Posted

Immutable. To correct this, post a compensating movement that references it — the corrected state and the record of correction stay the same object.

Effect

FromSITE-4/A/12/03
ToVARIANCE:kestrel
Quantity 12
Item
88213-K — Ambient pallet wrap
Lot
LOT/2026-0114
Owner
Kestrel Foods
Reason code
COUNT_SHORT
Document
CS-8812 line 41
Net at source
−12
Net at destination
+12
System net
0 — always, by construction

Chain

Verified
prev_hash
7b21f0a9c4e8…3d81
row_hash
9f3a44e10b7c…c1f2
Tenant sequence
1,000,412
Partition
stock_movement_2026_08

Chaining is per-tenant, which serialises movement posting for a tenant at roughly 50–100µs — a ceiling near 10–20k/second, well above the 2k/minute target. Per-(tenant, site) chaining with a daily Merkle root is the escape hatch if it ever binds.

Attribution

Actor
op-4471 · S. Okonkwo
Role
Floor Operator
Device
TC-52-014
Idempotency
8f21-b40c-9d33
client_seq
44,118

The human and the device are recorded separately. An attestation built on device IDs is worthless in a dispute.

Clock

occurred_at
14:02:47 device
recorded_at
14:03:11 server
clock_skew_ms
24,000

Timelines display by occurred_at because that is what happened on the floor. Balances, sequencing and attestation use recorded_at — a tamper-evident chain cannot be ordered by a clock the client controls.

Post movement

The only write path to a balance. Every movement needs a source account, a destination account, a positive quantity and a stated reason — there is no field on this form that sets a quantity to a value.

Movement

Document RCV-44215
External supply is an account, never null.
Units are neither created nor destroyed — both sides are required.
Ambient pallet wrap, 500mm × 300m
Custody travels with the lot, not the bin.
Always positive. Direction comes from the accounts above.

Receiving

Inbound. Every line posts EXTERNAL:{supplier}bin. External supply is an account, so a receipt conserves units like any other movement.

DocumentRCV-44215Dock 3 · Acme Supplies
Expected2,400from PO-9912
Received1,80075% complete
Discrepancy−6001 line short
LineItemLotExpectedReceivedDeltaTo binStatus
0188213-KLOT/2026-01146006000A/12/03Matched
0255810-QLOT/2026-02331,2001,2000B/09/07Matched
0344102-TLOT/2026-02206000−600Short

Fulfillment

Outbound pick. binEXTERNAL:{customer}. Availability is checked against on_hand − active_reservations under a per-position lock.

OrderOwnerItemOrderedAvailablePickedFrom binStatus
SO-77401Kestrel Foods88214-M20012200C/02/11Picked
SO-77402Kestrel Foods73390-X5123,584512F/01/02Picked
SO-77403Northvale Ltd90551-B40000Cannot allocate
SO-77404Aldgate Supply Co55810-Q527652B/09/07Last unit
409 negative_position

SO-77403 cannot be allocated: 90551-B is at zero. The API returns the current position in the error body so the picker is shown what is actually in the bin rather than a generic failure.

Last-unit contention

SO-77404 takes the final 52 units. This is the one genuine read-modify-write in the system, so it takes a pessimistic per-position advisory lock — two orders promised the same unit is a customer-facing broken promise, not a data inconvenience.

Transfer

Inter-bin and inter-site. Owner never changes — a transfer that crossed owners would be a title transfer, and the database refuses to let the two be confused.

In-transit transfer

TRF-10234

Two movements, not one

An inter-site transfer posts a dispatch and a receipt, with an in-transit account between them. Units are never in two places, and never in none.

SITE-9/Y/00/04
↓ dispatch
TRANSIT:site-9→site-4
↓ receipt on arrival
SITE-4/Y/00/01

If the trailer never arrives, the units sit visibly in transit rather than disappearing from one site's balance and never reaching the other's.

Title transfer

Moving units between two owners. Not an inventory event — a transfer of legal title, and it must be impossible to do by accident.

Paired document

TTL-00089
Required. A title transfer with no paper behind it is not defensible.
Cannot be you. Enforced by CHECK (approved_by IS DISTINCT FROM created_by).

What gets written

Two movements in one transaction. The bin does not change — only custody does.

FromToQty
A/04/18
Northvale
TITLE:northvale640
TITLE:penrose A/04/18
Penrose
640

Both owners' attestations show this event from their own side, referencing the same contract. Neither can be produced without the other.

Count sessions

Cycle counts by zone. A session flagged above the variance rate is treated as a probable process failure, not as hundreds of individual stock problems.

SessionZoneOwnerOpenedControllerLinesVariancesRateStatus
CS-8812A/12Kestrel Foods13:40ctl-0331961111.5%Open
CS-8811B/09Aldgate Supply Co11:02ctl-03311443121.5%Flagged
CS-8810F/01Kestrel Foods08:15ctl-01176223.2%Closed
CS-8809A/04Northvale LtdYesterdayctl-011721062.9%Closed

CS-8812

Open

Zone A/12 · Kestrel Foods · opened 13:40 by ctl-0331

Two operators counted bin A/12/03. Both counts are in the ledger.

The system does not pick a winner. Both operators really did count what they recorded, and the disagreement between them is the strongest available signal that something is wrong — silently resolving it would discard exactly the evidence the controller needs.

BinItemCounterTimeCountedExpectedDeltaOutcome
A/12/0388213-Kop-4471 · S. Okonkwo14:02:47 1,1921,204−12Variance
A/12/0388213-Kop-2210 · J. Halloran14:09:15 1,2041,2040Disagrees
A/12/0488213-Kop-4471 · S. Okonkwo14:11:02 4314310Matched
A/12/0988213-Kop-2210 · J. Halloran14:14:38 208212−4Variance

Disagreement on A/12/03

Send to triage
First count · 14:02:47 1,192 op-4471 · device TC-52-014 · online, recorded 14:03:11
Recount · 14:09:15 1,204 op-2210 · device TC-52-009 · online
Neither count was discarded. The variance of 12 units sits in VARIANCE:kestrel until a human disposes of it.

Variance triage

412 open. Ranked by exposure — extended value × contractual SLA weight — because the real question is not "what is different" but "which of these can become a claim".

Open412across 4 owners
Above threshold12above the owner's threshold
Total exposure£18,402extended value
Median age4holdest 3d
ExposureItemOwnerAccountUnitsValueSLAAgeSessionGate
£5,28629944-HAldgate Supply CoVARIANCE:aldgate −472£3,7761.4×3hCS-8811 2nd approverDispose
£1,00844102-TKestrel FoodsVARIANCE:kestrel −240£8401.2×1dCS-8802 2nd approverDispose
£21488213-KKestrel FoodsVARIANCE:kestrel −12£1781.2×23mCS-8812 ControllerDispose
£11255810-QAldgate Supply CoVARIANCE:aldgate +8£801.4×4hCS-8811 ControllerDispose

Exposure is extended value × SLA weight — £3,776 × 1.4 = £5,286. SLA weight comes from the owner's contract. A discrepancy of the same value is not the same problem for a client with a 4-hour reconciliation SLA as for one with 30 days.

Dispose variance

29944-H · Aldgate Supply Co · −472 units · £5,286 exposure

Disposition

Configured per owner. Aldgate's contract defines six; another client may define three.
Cancel

Separation of duties

Proposed byctl-0331 · you
Approvernot selected

£5,286 is above Aldgate's £250 threshold, so this needs a second approver who is not you. Enforced by CHECK (approved_by IS DISTINCT FROM created_by) — it holds against a direct API call with a valid token, not just against this form.

Why: the person who found the discrepancy has the strongest incentive to make it go away.

What gets posted

Disposition does not erase the variance. It moves the units on again, with a cause.

VARIANCE:aldgate
↓ 472 · SUSPECTED_MISPICK
WRITEOFF:aldgate

Aldgate's attestation will show the units entering variance at 11:04, sitting there for six hours, and being written off at 17:22 by two named people under a stated reason.

Quarantine

27 movements accepted but not yet reconciled. Each is a real physical action that failed validation on reconnect — quarantined, never rejected.

RefItemAttemptedQtyOperatorDeviceFailed becauseEvidenceAge
QRN-009188213-KA/12/03cust-8871 6op-4471TC-52-014 Bin emptied while offlinescan photo3h 12m
QRN-009055810-QB/09/07B/09/08 24op-1180TC-52-022 Destination bin mergedscan2h 40m
QRN-008973390-XF/01/02VARIANCE:kestrel 96op-3302TC-52-031 Count session already closedscan1h 08m
QRN-008829944-HEXTERNAL:acmeB/09/07 500op-2210TC-52-009 Lot deleted during mergescan photo55m

Devices

48 enrolled handhelds. Offline is an ordinary condition here — racking dead zones, cold rooms that behave like Faraday cages, and trailer interiors are daily, not exceptional.

Synced42
Offline664 queued writes
Clock skew > 5m1
Battery < 20%3
DeviceModelOperatorZoneLast syncQueuedSkewBattState
TC-52-014Zebra TC52op-4471 · S. OkonkwoA/1214:26:33024ms78%Synced
TC-52-031Zebra TC52op-3302 · M. DubeF/0113:48:02341%Offline 38m
TC-52-007Zebra TC52op-1180 · A. ReyesC/0213:12:556116%Offline 74m
TC-52-044Honeywell CT30op-2210 · J. HalloranA/0114:20:11041m92%Clock skew

Owners

Whose goods these are. Distinct from the tenant — this is the entity Sortly and Zoho have no concept of, and the axis every table, permission and attestation partitions on.

OwnerContractSitesSKUsUnits heldSLA weightThresholdOpen variancesPortal
Kestrel FoodsMSA-2024-0088SITE-4, SITE-9 612184,2201.2×£500188 ActiveAttest
Northvale LtdMSA-2025-0141SITE-4 33871,9041.0×£50094 ActiveAttest
Aldgate Supply CoMSA-2026-0007SITE-4 24129,1181.4×£250118 ActiveAttest
Penrose GroupMSA-2026-0114SITE-9 9311,6621.0×£1,00012 OnboardingAttest

Kestrel Foods

Active

Contract MSA-2024-0088 · onboarded 2024-03-02 · SITE-4, SITE-9

Units held184,220
Active SKUs612
Open variances188£6,204 exposure
Attestations41last 2026-08-01

Contract terms

SLA weight
1.2× — applied to variance exposure ranking
Reconciliation SLA
24 hours from variance raise
Dispute response
4 hours
Disposition threshold
£500 — above this needs a 2nd approver
Retention
18 months hot, then cold archive
Portal access
3 users · read-only, owner-scoped

Disposition reasons

Configured per owner. A reason set that does not match how this client actually operates produces dispositions nobody can defend.

SUSPECTED_MISPICKMISLABELLED_RACK DAMAGE_UNRECORDEDSUPPLIER_SHORT_SHIP COUNT_ERRORTHEFT_SUSPECTED

Attestation

A point-in-time account of what we hold for a client, readable by someone who has never been in a warehouse, with every line traceable to the movements that produced it.

Kestrel Foods · as at 2026-08-19 14:26 UTC

Chain verified
ItemDescriptionLotHeld atUnitsNote
88213-KAmbient pallet wrapLOT/2026-0114Tilbury DC1,635
88213-KAmbient pallet wrapLOT/2026-0088Tilbury DC212Expiring 44d
73390-XFrozen carton, 12 × 400gLOT/2026-0201Tilbury DC4,096
88214-MChilled tray linerLOT/2026-0177Tilbury DC212
88213-KAmbient pallet wrapLOT/2026-0114Awaiting reconciliation6Quarantined 3h
88213-KAmbient pallet wrapLOT/2026-0114Variance account12Under investigation
73390-XFrozen carton, 12 × 400gLOT/2026-0201Awaiting reconciliation96Quarantined 1h
7 lines · 184,220 units total across 612 SKUs seq 1,000,412

Why the last two rows matter

Most inventory systems would show this client 184,202 units and say nothing about the other 18. Here the quarantined and variance units appear on the client's own statement, with their age and status, because every unit is always in an account. "Unaccounted for" is not a state this system can represent.

Chain

Head seq
1,000,412
Head hash
9f3a44e1…c1f2
Verified
2,214,908 rows
Anchored
Not yet — see below

Open question: a hash chain proves the record was not altered by anyone who does not control the database. It does not, on its own, prove anything to a court about an operator who controls their own backups. Daily Merkle-root anchoring to an external service is the fix, and whether it is legally necessary is a question for a logistics contracts lawyer, not a designer.

Disputes

Raised by clients against a specific balance line. Bound to the ledger position, so the resolution stays attached to the record it resolved — rather than living in someone's inbox.

RefOwnerItemPositionDisputedOur figureRaisedSLAStatus
DSP-0044Kestrel Foods88214-MC/02/11 25221212:02 1h 36m leftOpen Trace
DSP-0043Aldgate Supply Co29944-HVARIANCE:aldgate 5000Yesterday BreachedInvestigating Trace
DSP-0042Northvale Ltd90551-BA/04/18 40002026-08-14 MetResolved Trace

DSP-0044 · what the account manager can answer without phoning the site

12:02 Client asserts 252 units at C/02/11
13:58 C/02/11EXTERNAL:cust-8871 · 200 · PICK · op-1180 · b3f0…7c
09:15 EXTERNAL:acmeC/02/11 · 412 · RECEIPT · op-2210 · d18a…52
08:02 Opening balance 0

412 received − 200 picked = 212. The client's 252 predates the 13:58 pick.

Suppliers

Integration-facing and deliberately thin in v1. In a 3PL the operator does not own the goods, so replenishment is the client's decision — we record what arrives, we do not decide what should.

SupplierAccountOwnerChannelOpen POsOn-timeLast inboundStatus
Acme Supplies LtdEXTERNAL:acmeKestrel FoodsEDI 856496.2%14:01Active
Brookfield PackagingEXTERNAL:brookfieldNorthvale LtdCSV288.0%YesterdayActive
Halden Cold ChainEXTERNAL:haldenKestrel FoodsREST199.1%2026-08-17Active
Penrose DirectEXTERNAL:penrose-dPenrose GroupManual0Onboarding

Purchase orders

Inbound expectation versus what actually arrived. A PO is not stock — nothing here affects a balance until a receipt posts movements.

POSupplierOwnerExpectedLinesOrderedReceivedOpenStatus
PO-9912Acme Supplies LtdKestrel Foods2026-08-1932,4001,800600Part received
PO-9908Halden Cold ChainKestrel Foods2026-08-1714,0964,0960Closed
PO-9915Brookfield PackagingNorthvale Ltd2026-08-2128,00008,000Awaiting
PO-9901Acme Supplies LtdKestrel Foods2026-08-12412,00011,400600Short — claim open

Reservations

Soft claims against available stock. Not movements — a reservation has not moved anything. available = on_hand − active_reservations, checked under the same per-position lock as a post.

RefOrderOwnerItemPositionReservedOn handAvailableExpiresStatus
RSV-3301SO-77401Kestrel Foods88214-MC/02/11 2002121216:00Active
RSV-3302SO-77402Kestrel Foods73390-XF/01/02 5124,0963,58418:00Active
RSV-3299SO-77398Aldgate Supply Co55810-QB/09/07 247676Expired 13:00Expired
RSV-3288SO-77390Kestrel Foods88213-KA/12/03 1201,2041,084TomorrowActive
Open architectural question

Reservations currently live beside the ledger rather than in it, on the reasoning that a reservation has not moved anything. But RSV-3299 expired at 13:00 and simply stopped applying — which is an unrecorded state change, and a client auditing why stock was unavailable at 12:55 has nothing to look at. Moving reservations into the ledger as zero-quantity claim events is the likely resolution, and it is not settled.

Users

Membership binds a user to a tenant, then to a site scope, then to an owner scope. All three are enforced by row-level security, not by the application.

UserIDRoleSite scopeOwner scopeAuthLast activeStatus
R. Vanceadm-0004Tenant AdminAll sitesAll ownersSSO · Okta14:22Active
D. Ferreiramgr-0088Ops ManagerSITE-4All ownersSSO · Okta14:19Active
K. Adeyemictl-0331ControllerSITE-4Kestrel, AldgateSSO · Okta14:26Active
S. Okonkwoop-4471Floor OperatorSITE-4 · zone AActive work onlyBadge + PIN14:26On shift
M. Dubeop-3302Floor OperatorSITE-4 · zone FActive work onlyBadge + PIN13:48Offline
T. Brightcli-0912Client User— noneKestrel Foods onlyPortalYesterdayActive

Client users have no site scope at all. They never see warehouse layout or operator names — only their own goods.

Roles

Six roles. The greyed cells are not "not yet built" — several of them are constraints the database refuses to allow, including for the role that can do everything else.

CapabilityTenant AdminOps ManagerControllerFloor OperatorClient UserService acct
Post movements YesYesYes In scopeScoped
Read balances AllSiteSite Active workOwn ownerScoped
Open / close count sessions YesYesYes
Dispose variance below threshold YesYesYes
Approve variance above threshold YesYes Not own
Void a document YesYes
Grant roles / onboard owners Yes
See other owners' data YesSiteAssigned NoZero rowsScoped
Set a stock quantity ImpossibleImpossibleImpossible ImpossibleImpossibleImpossible
Modify or delete a movement ImpossibleImpossibleImpossible ImpossibleImpossibleImpossible

Why Tenant Admin cannot do these two things

Not a policy that an admin could change, and not a permission flag with a default of false. The application role holds no UPDATE or DELETE grant on either table — there is no privilege to escalate to, because the privilege was never created.

UPDATE stock_movement SET qty = 100 WHERE id = ...;
ERROR:  OS001: stock_movement is append-only

UPDATE stock_balance SET qty = 100 WHERE ...;
ERROR:  permission denied for table stock_balance

There is no admin flag, support tool, or migration that turns this off. That is the whole product.

The honest risk

This position has never met an angry operations director at 2am during a peak-season count. There will be pressure for an override, and the answer is that there is none — the escalation path is a compensating movement with an executive reason code.

Whether that path is fast enough to be usable under real pressure is untested. If override requests turn out to be frequent and legitimate, the thesis is wrong and should be revised in daylight rather than defended.

Instrumented: count of 422 quantity_not_settable responses, and support tickets asking for an override.

Integrations

Honest about what is real and what is stubbed.

ConnectionTypePartnerDirectionDocsLast message24hStatus
Acme EDIX12 via VANAcme SuppliesInbound856, 81014:0142Stub
Kestrel WMS feedX12 via VANKestrel FoodsBidirectional940, 94513:44118Stub
Halden RESTRESTHalden Cold ChainInboundASN2026-08-173Live
Brookfield CSVCSV dropBrookfield PackagingInboundPO, ASNYesterday1Live
Owner webhooksWebhookAll ownersOutboundmovement.posted14:2638,204Live
ZPL print serverNetwork printSITE-4Outbound4×6 label0Stub

API keys

Service accounts. Scoped per endpoint, IP-allowlisted, and with no interactive session — a key cannot log into this console.

NameKeyOwner scopeScopesRate classAllowlistLast usedStatus
Kestrel ERP syncos_live_8f21…9d33Kestrel Foods movements:write
balances:read
document-write 2 CIDRs14:19Active
Portal read-onlyos_live_4c88…a071All owners balances:read
attestations:read
read 1 CIDR14:26Active
Scan gatewayos_live_e019…3d55All owners movements:writescan-write Site subnet14:26Active
Legacy BI exportos_live_2200…7712All owners reports:readreport — any2026-06-02Stale 78d
Why scan-write is its own rate class

It has a reserved throughput floor per site that no other class can consume. Under global pressure, read and reporting traffic degrade first — always. The reason is a product reason, not an infrastructure one: a picker who receives a 429 writes on paper and reconciles at end of shift, which destroys the completeness of the ledger the entire product depends on. Every other class can wait. That one cannot.

Audit log

Everything that is not stock — role grants, location renames, threshold changes. Append-only and hash-chained like the ledger, but deliberately a separate table.

WhenActorEventTargetBeforeAfterHash
14:02:11adm-0004threshold.changedAldgate Supply Co£500£250a91c…44
13:40:55ctl-0331count_session.openedCS-8812zone A/127d02…19
11:18:03adm-0004role.grantedctl-0331Floor OperatorController3e88…b2
09:44:20mgr-0088location.renamedB/09/07B/09/07-OLDB/09/07c410…7f
04:00:00systemsnapshot.completedAll positions1,204,882 rows0b57…e3
Yesterdayadm-0004api_key.createdos_live_e019…scan-write9911…20

Settings

Every number on this page is a hypothesis — a guess with no usage data behind it. They are configurable precisely because none of them is defensible yet.

Variance

Hypothesis
GBP extended value per variance line. Set too low and managers rubber-stamp, which is worse than no threshold at all.
Percent of lines in variance. Above this, the session is flagged as one probable process failure rather than N independent losses.

Enforced by a database constraint regardless of this switch. The toggle only controls whether the UI offers the action.

Retention & sync

Hypothesis
Months online before cold-tiering to Parquet. Should be set from real dispute lookback windows in 3PL contracts — currently anchored on nothing.
SKUs held per handheld. Almost certainly far larger than the real number of shift-active SKUs.
Minutes. Above this, human-facing timelines show a skew badge.
Minutes before a handheld locks. Shift and outbox survive the lock.

State gallery

Every empty, loading and error state in one place, so they can be checked against each other rather than discovered one at a time.

Empty — three distinct kinds

Collapsing these into one "no data" screen is a common and costly mistake. They mean different things and need different actions.

No movements posted
Nothing has moved at this site yet. Post the first movement to start the ledger.
Post movement
No movements match these 3 filters
Owner: Penrose · Zone: F/01 · Today. There is data here — your filters exclude it.
You don't have access to this owner
Your scope covers Kestrel and Aldgate. Request access from an administrator.

Loading

Skeleton — 400ms delay, no shimmer

Static opacity pulse, 0.6 → 1.0 over 1600ms. No travelling highlight — a shimmer sweep is horizontal motion across a data region. Nothing renders before 400ms, because a sub-400ms flash is more disruptive than the wait.

Spinner — only where shape is unknowable

Used when the result has no predictable shape. Loading is always scoped to the region that is loading — navigation and the scan affordance stay live. Never a full-screen block.

Error — four tiers, matched to recoverability

88213-K Failed to post — bin emptied while offline. Tier 2 — row. The row is never removed; a failed record is still a record.
Offline is not an error · 3 queued — turns green and dismisses itself on drain

A recoverable error never gets a modal. Modals are for decisions, not notifications — an operator dismissing a modal mid-scan loses their place in the pick.

Error pages

Full-page failures. Each states the cause and a recovery path — never just a code.

403 — not in your scope
Your membership covers SITE-4 and two owners. Nothing outside that scope is readable from this account — including whether it exists.
Back to dashboard
404 — no such record
The document or item ID in this URL does not exist in your tenant. Check the reference, or search for it.
Search
500 — we could not read the ledger
Reads are failing. Writes are unaffected — keep scanning. Queued work is safe on device and will post.
Retry
TC-52-014
Enrolled
Device trusted

Who is on shift?

Every movement you post carries your operator ID, not this terminal's.

op-4471 · TC-52-014
Online
Pick · SO-77401 · line 2 of 6

Scan the label

GS1-128 · Code 128 · QR
Go to
C/02/11
Pick
200
Item
88214-M
Chilled tray liner, 400 × 600
op-3302 · TC-52-031
Offline · 3
No signal · 3 queued

3 movements waiting

All three are saved on this device and will post in order when you get signal. Nothing here is lost by locking, rebooting or swapping the battery.

88214-M
A/12/03 → cust-8871 · 200
Queued
73390-X
F/01/02 → cust-8871 · 512
Queued
88213-K
A/12/03 → count CS-8812 · 1,192
Queued

Because every write is an append and never an update, these replay in order on reconnect. There is nothing to merge and no one's work to discard — if two of you worked the same bin offline, both movements survive.

op-4471 · TC-52-014
Online
Count CS-8812 · bin 41 of 96

A/12/03

88213-K · Ambient pallet wrap

Counted 1,192

The expected figure is deliberately not shown until you submit. Seeing it first changes what people count.

op-4471 · TC-52-014
Online
Posted
1,192 counted at A/12/03 · seq 1,000,412
Recorded on the server at 14:03:11. This is not a queued state.
Next task

Putaway

Take from
Dock 3 · pallet 4
Put to
F/01/02
Frozen · 12 bays free
Qty
1,200
Item
73390-X
Frozen carton, 12 × 400g · LOT/2026-0201
op-3302 · TC-52-031
Offline · 3
Saved for review
Your record is kept. A controller will reconcile it.

What happened?

You moved stock but the system disagrees about the bin. We keep what you recorded — the movement already happened, and throwing away your record would destroy the only evidence of it.

Add a photo
Attached to the record permanently
OmniStock
Client portal

Your goods, held at Meridian 3PL

Read-only access to your own inventory, statements and disputes. You will not see any other client's data — not hidden, not filtered out at the screen: the database returns nothing.

Meridian staff sign-in
OmniStock
Kestrel Foods
Sign out

Your holdings

As at 2026-08-19 14:26 UTC. Every figure traces to the movements that produced it.

Statement
Units held184,220across 612 SKUs
Awaiting reconciliation6oldest 3h
Under investigation12variance raised 14:03
ItemDescriptionLotExpiryUnitsStatus
88213-KAmbient pallet wrap, 500mm × 300mLOT/2026-01142027-01-141,635HeldQuery
73390-XFrozen carton, 12 × 400gLOT/2026-02012026-12-014,096HeldQuery
88213-KAmbient pallet wrap, 500mm × 300mLOT/2026-00882026-10-02212Expiring 44dQuery
88214-MChilled tray liner, 400 × 600LOT/2026-01772026-09-11212QueriedView
88213-KAmbient pallet wrap, 500mm × 300mLOT/2026-01146Awaiting reconciliationQuery
88213-KAmbient pallet wrap, 500mm × 300mLOT/2026-011412Under investigationQuery
Why the last two rows are shown to you

18 of your units are not currently on a shelf — 6 were recorded by a handheld that was offline and are being reconciled, and 12 are in a variance account after a stock count found fewer than expected. Most systems would simply show you 184,202 and not mention it. You are seeing them because every unit we hold for you has to be somewhere, including the ones we cannot currently put a hand on.

OmniStock
Kestrel Foods
Sign out

Statements

A point-in-time account of what we hold for you, signed and chain-verified.

StatementAs atLinesUnitsChainIssued
ATT-2026-08-012026-08-01 00:00612179,004Verified2026-08-01
ATT-2026-07-012026-07-01 00:00598166,880Verified2026-07-01
ATT-2026-06-012026-06-01 00:00571154,220Verified2026-06-01

What "chain verified" means

Each movement affecting your goods is linked to the one before it by a cryptographic hash. Changing any historical record would break every link after it, which is detectable.

Rows verified
2,214,908
Head hash
9f3a44e1…c1f2

What it does not yet mean

The chain is currently held by Meridian. It proves the record has not been altered by anyone who does not control this database — it does not, on its own, prove that to a third party in a claim. Independent anchoring is on the roadmap and is not live. We would rather tell you that than let the word "verified" do more work than it has earned.

OmniStock
Kestrel Foods
Sign out

Raise a query

Bound to a specific line of your holdings, so the answer stays attached to the record it is about.

Query DSP-0044

Open

Response time

1h 36m remaining under
your 4-hour SLA

Your open queries

DSP-0044Open
DSP-0031Resolved
DSP-0022Resolved