Dev Release #7Three portals, one tradeRead the notes
Dev Releases · Release #7

Dev Release #7 — Three Portals, One Trade

We built three portals end-to-end this release. Client. Supplier. Logistics. Each one is a working front, not a viewer. The same order shows up in all four views — operator at the center, the other three on the perimeter — and each party sees only what they need. Clients never see the factory. Suppliers never see the final buyer. Logistics moves the cargo without touching the money.

≈ 12 min read · 11 sections
3 portals shippedClient · Supplier · Logistics
Same order, 4 viewsOperator at the center, three on the perimeter
Privacy at data layerIdentity boundaries enforced server-side

Trade was always multi-party. Now the system is too.

Real trade involves at least four parties. The operator coordinating the deal. The client who placed the order. The supplier producing the goods. The freight partner moving the boxes. Each one has a different job, different information, different exposure — and a real interest in not seeing each other's full picture.

Until this release, only the operator had a system. The other three were on the outside, working off emails, PDFs, spreadsheets, and whatever the operator chose to share. The platform understood the trade. The trade itself was still being run by hand.

This release is the multi-party layer. Three new portals shipped end-to-end. The client has their own portal. The supplier has theirs. The logistics partner has theirs. Each one is a working front — not a status page, not a viewer onto operator data, not a read-only summary. They are the real surface for each party to do their job. The operator sits in the center coordinating. Everyone else now sits at the table with a seat of their own.

The same order appears in all four portals at the same time. Different views. Different scopes. One trade underneath.

Three portals. End-to-end. Working fronts, not viewers.

The client portal is where the buyer lives. They track their orders from the moment a deal is confirmed through delivery. They see production progress, shipment milestones, invoices owed, payments made, claims they have raised, sample submissions, and the documents associated with their trade. They can chat with the operator about any of it. They never see which factory the operator chose, what the operator paid for the goods, or which other clients the operator works with.

EDMA Client Portal home screen showing orders, shipments, invoices, and documents
Client portal — the buyer's view of their trade

The supplier portal is where the factory lives. They run their own catalog of products, their own production board, their own compliance matrix, their own documents library, their own task queue, their own messaging, their own invoices and proformas, their own finance hub with AR aging and statements, their own performance dashboard, and their own organization settings. Every operator section is mirrored on their side with their own data scope. They see the operator's purchase orders without seeing the operator's resale price, the final client, or any other supplier the operator works with.

EDMA Supplier Portal home screen showing production, compliance, invoices, and tasks
Supplier portal — the factory's view of their work

The logistics portal is where the forwarder lives. They handle bookings, dispatch, shipments with milestones and exceptions, rate sheets, RFQs, and invoices. They see enough operational context to do their job: where the cargo is, what the operator booked, what the customs status is, what the next milestone is. They do not see the trade financials underneath — they see freight cost, not the value of the goods inside the container.

The operator portal — already live — sits at the center. The operator sees everything: every order, every party, every dollar, every milestone, every document. They are the only role in the system with full visibility.

EDMA Logistics Portal dashboard showing bookings, shipments, milestones, and dispatch
Logistics portal — the forwarder's view of the cargo

One order. Four views. Each one shows exactly what that party should see.

This is the most useful way to understand what we built. Pick a real order — Client A buys 500,000 examination gloves from the operator at $0.12/unit; the operator sources from Factory B at $0.08/unit; the cargo moves through Forwarder C from Shanghai to Rotterdam. One trade. Four perspectives.

The operator sees the whole thing. Order detail shows the client, the supplier, the production schedule, the shipment plan, the documents, the financial picture — both the receivable from the client and the payable to the supplier, the margin on the line, the tax bucket, the QC plan. Every action they take cascades into the other portals automatically.

Operator Order Detail page showing client, supplier, production, shipment, and full financials
Operator view — full visibility into every party and every dollar

The client sees their side. Order number, expected delivery, what's been shipped, what's been invoiced, what's been paid, what documents exist for the order, what claims they have open. The supplier name is not in their view. The operator's cost is not in their view. The factory location is not in their view. They see their order and the parts of the operation that involve them — nothing more.

Client Order Detail page showing what the buyer sees — supplier and cost information redacted
Client view — order, delivery, invoices, documents. No supplier name, no factory location, no operator cost.

The supplier sees their side. Purchase order from the operator, what they have to produce, the production lot status, the QC plan, the sample submissions, the invoices they have issued, the proformas in flight. The final client name is not in their view. The operator's resale price is not in their view. The operator's margin is not in their view. They see what they are being paid to make and how to make it correctly — nothing more.

Supplier Order Detail page showing what the factory sees — client identity and operator margin hidden
Supplier view — PO, production, QC, invoices. No client name, no resale price, no operator margin.

The logistics partner sees the cargo. Shipment milestones from origin to destination, bookings and capacity, dispatch status, customs events, exceptions if anything is off track, the rate they agreed to, the invoice they are owed. They do not see what the goods are worth or who is paying whom. They see what they need to do their job and nothing else.

Four portals. One order. Each view is curated to the role.

Logistics Shipment Detail page showing what the forwarder sees — trade financials hidden
Logistics view — cargo movement, milestones, dispatch. No trade financials, no goods value.

Privacy is not a render decision. It is the architecture.

The temptation when building a multi-party portal is to redact fields at the UI layer. Show everything in the database, hide some of it with a CSS rule. This is how most enterprise portals work, and it is how data leaks happen — every new field, every new API endpoint, every new export is one mistake away from exposing what should not be exposed.

We did not do that. The privacy boundary lives at the data layer. When a supplier session hits an order endpoint, the query is rewritten before it runs — the supplier sees the order rows where they are the producer, never the rows where they are not, and the SELECT statement does not return the client name column in the first place. The same applies in reverse for the client. The data the supplier never sees does not arrive at their browser. The data the client never sees does not arrive at theirs.

This release closed multiple scope gaps that would have leaked across the boundary if left unfixed — a body-ID scope gap on POST /plans, a Customer-Request endpoint that could have exposed an order/deal/manufacturer link, a Saved Plans tab that needed a module-level portal-type guard. A universal defense-in-depth guard now sits in front of every operator endpoint at the framework level — even if a route forgets to scope itself, a non-operator session will be refused before the handler runs.

Because privacy is scope-enforced at the route, the query, and the event level rather than redacted at render, every new feature, every new field, every new export inherits the same boundary automatically. We do not have to remember to hide the client name on the next page we build. The client name is not in the supplier's data in the first place.

The most interesting thing we built this week.

The cross-portal nervous system.

Three portals could have shipped as three separate apps that happen to share a logo. That would have been easier and almost worthless. The point of a multi-party platform is that the parties actually collaborate — and collaboration needs a nervous system underneath the portals that fires when one party acts and updates the others.

That nervous system is what we built this week. Cross-portal events are not bolted on. They are the substrate. When the supplier accepts a match the operator originated, the operator's proposal record gets the event automatically and the operator-side timeline shows it. When the operator approves a sample submission, the supplier's task list lights up and the next step opens. When the client raises a claim, the operator and the supplier (if relevant) both see it linked to the right order and the right lot. When a payment lands, the AR aging on the supplier side recalculates, the AP picture on the operator side updates, and the client's invoice flips to paid — all in one heartbeat.

Tasks-from-chat modal showing the selection toolbar and structured task creation flow
Tasks-from-chat — select messages → structured task → cross-portal link

One ChatLaunchButton. Eight placements. Three portals. A single shared component lives on the order detail, lot detail, sample card, claim, manufacturer profile, client profile, entity-search picker, and task detail. Tap it anywhere and you start a thread with the right counterparty about the right entity. The operator sees it in their inbox. The supplier sees it in theirs. The client sees it in theirs. Same backend. Three audiences. The counterparty picker scopes to who you are allowed to talk to.

Tasks-from-chat is where this earns its keep. You are in a thread with the supplier discussing a production delay. You select two or three messages. Click "Make this a task." The selected messages become a structured task with auto-generated context, the task lives in both portals, and a system message in the chat shows the cross-link both ways. The conversation generated the task. The task references the conversation. No one had to write a summary.

Entity-search picker is the connective tissue between text and structure. When you create a task, when you start a conversation, when you reference something inside a thread — the picker autocompletes across clients, manufacturers, orders, lots, samples, deals. It is mounted on the operator portal and on every external portal with the right data scoping for each.

This is the layer that makes three portals feel like one platform instead of three.

One inspection workflow. Every product. Both portals.

Before this release, quality control was a sketch. This release ships QC v1: a real, working, product-agnostic inspection workflow that runs on both the operator portal and the supplier portal.

The backend treats inspections as the same record type regardless of what is being inspected. Parameters and defects are stored generically, then drawn from the taxonomy at render time — an inspection on examination gloves uses the glove-specific parameters published in the type definition; an inspection on rice uses the rice-specific parameters; the same UI renders both correctly. No per-product inspection forms to maintain.

QC inspection detail page showing product-agnostic parameters and defects sections
Six-section inspection — product-agnostic, taxonomy-driven

When an inspection records a defect, the system auto-generates a follow-up task — rework the lot, escalate, repair, whatever the playbook calls for. The inspection deep-links from the lot detail page so anyone landing on a lot can see its QC history. Related claims thread against the inspection so the QC evidence and the dispute conversation share the same record trail. The PDF generator produces a clean inspection report and indexes it into the documents library automatically — searchable, audit-trail-locked, versioned.

QC mounts on both the operator portal (the operator sees every inspection across every supplier) and the supplier portal (the supplier sees only their own). The shape of the page is the same. The scope of the data is not.

Every document a transaction touches is now indexed.

The documents engine from Release #6 covered the documents that lived in a transaction — commercial invoices, packing lists, certificates of origin, customs declarations. This release extended the index to every other file uploaded to the system.

Phase 1 picked up production updates (photos and PDFs attached to lots in progress), claim evidence (attachments on defects and disputes), and operator sample photos. Phase 2 added certificates (compliance attestations, lab reports, expiry-tracked records) and the operator's sample photo library. Phase 3 picked up the long tail — product custom-field files (data sheets, technical drawings attached to a product spec) and branding assets (workspace logo, avatar, the visual identity carried onto generated documents).

The documents database is now a real database of everything uploaded to EDMA. Search "lab report for chemo gloves Q3" and the system finds it whether it was filed as a certificate, attached to a production lot, or referenced from a claim. The portal scoping applies here too — the supplier sees only documents from their own work, the client sees only documents from their own trades, the operator sees everything.

The rest, in shorter form.

Taxonomy cleanup. The product taxonomy started at 3,029 types across all sectors. It now sits at 2,315 — a 24% reduction. Most of the cut was aliases, near-duplicates, and accidentally-promoted categories. We aligned HS codes against the 2022 standard, promoted the right types to leaves (Examination Gloves, Rice families), and added per-family field specialization so chemo gloves get fields surgical gloves do not. Medical taxonomy alone went from 556 to 450. The cleanup is invisible to anyone using the platform; what they see is fewer junk choices in the type picker and faster auto-detect on product creation.

Marketing site IA. The public marketing surfaces were running with drifted per-page nav and footer copies. They now share one mega-nav and one footer across every page — a single chrome.css and chrome.js, a single nav-data file driving the IA. New deep-dives went up under /product/communications and /product/orders/documents-collection.

Security. A module-level portal-type guard now sits in front of every operator endpoint at the framework level. The Saved Plans + Demand Forecast tabs and every operator route they touch are covered. Body-ID scope gaps closed on POST /plans and POST /planning/create-lots. Customer-Request leak plugged.

i18n. A full sweep added useT() to 165 components across 66 files. The operator and supplier and client portals are wired for translation; the menu now translates from a labelKey pattern; 740+ new keys went into the locale catalog.

What's running right now.

Operator portal — full coverage of Products, Manufacturers, Clients, Orders, Production, Shipments, Documents, Finance, Tasks, QC, Settings.

Client portal — Dashboard, Orders, Production, Shipments, Invoices, Documents, Claims, Samples, Messages, Analytics.

Supplier portal — operator-parity coverage across Catalog, Production, Compliance, Documents, Tasks, Messages, Invoices, Proformas, Finance hub, Performance, Settings.

Logistics portal — Dashboard, Bookings, Shipments, Dispatch, Rate Sheets, RFQs, Invoices, Settings. Driver-only contexts get a filtered nav (Overview, Shipments, Dispatch only).

Cross-portal nervous system — ChatLaunchButton on eight surfaces, tasks-from-chat with cross-link, entity-search autocomplete on all three external portals, "+ New conversation" in every inbox, auto-task generation on supplier↔operator events.

Quality control — unified product-agnostic inspection workflow on operator and supplier portals.

Documents — five-section structure plus cross-section indexing of every uploaded file.

Taxonomy — 2,315 types across 203 categories, HS-2022 aligned, with per-family field specialization.

The fifth seat. The public site. The roadmap update.

The financier portal is being built right now. A 45-page spec is locked. Financiers — banks, factors, funds, family offices — will get the fifth seat at the table. Operators publish receivables to a private marketplace. Financiers browse listings with operational signals attached: supplier reliability, client payment history, dispute rate. Settlement flows through a 0.25% financier-paid fee with an accrual ledger, monthly billing, auto-pay, and progressive suspension on non-payment. Subscription tiers from Browser (free) to Enterprise. The v1 architecture is designed so the v2 path — settlement routed through the EDMA L2 with the EDSD stablecoin — does not require a retrofit. Active development this week.

The public Trade OS site at edma.trade is about 90% built. The Trade Finance & Marketplace section, the audience cards, the pricing page, the operational signal narrative are all in place. The last 10% — final copy passes, the pricing v6 publication, the financier audience landing — is the priority work for the next release window. When this site goes live, public pricing becomes a competitive weapon against the SAP/Ariba stack.

The public roadmap will be updated to reflect what just shipped and what is coming. Three external portals were marked as in-progress on the previous roadmap snapshot — they are now done. The financier portal is the new active workstream. The logistics portal merge to main is the immediate next step.

From one-operator software to a network the trade runs on.

When this release closes, the operator is no longer the only party in the system. The client logs in to their portal and sees their orders. The supplier logs in to theirs and sees their production. The forwarder logs in to theirs and sees the cargo. The operator orchestrates everything from the center. None of them sees what they should not see, because the privacy boundary is in the data, not the rendering.

The financier is coming next. Five seats at the table by the end of the next release cycle. Same trade. Different scope. One system underneath enforcing who sees what.

This is the point where EDMA stops being software an operator runs and starts being a network the trade itself runs on.

Audited by
Current presale

Verify first. Then mint.

$EDM is the fee, burn, and governance token of the only Ethereum L2 designed to verify real-world events before they settle.

Community Chat

Five channels, one community. Pick where you live online; we'll meet you there.