You can build and run your own functioning instance of the Radish34 proof of concept here.
But if you want to see what it might be like for a group of companies to use the Baseline Protocol in a wider set of supply chain operations, here is an interactive visualization:
In the supply chain story we staged in this application the user can play the role of Buyer who wants to place an order with Suppliers for X number of widgets. They also can play the role of Supplier who works with the Buyer to fulfill their purchasing needs.
The story begins with the Buyer creating a Request for Proposals and sending it to several suppliers, getting proposals back, selecting one proposal, and then Baselining the MSA contract between the Buyer and Supplier.
Ahead of playing through the story there are a few setup tasks to make the whole prototype demo experience work. You first need to run the setup process in the development environment to make sure you configure your demo environment.
We broke down the supply chain procurement process into two phases; Contracting and Ongoing. The Radish demo only captures key parts of the contracting phase at this point in development. Supporting the ongoing phase of procurement will come very soon.
Buyer context: My R&D department has given me a request for a new part X for our product Y. I need to find two domestic suppliers for this part who can fulfill my expected 12 month volume.
Browse the list of suppliers in the Global registry (via the Radish App UI) for the supplier who carries part X.
Select two suppliers from the list who can deliver the approximate volume.
Click "Draft an RFQ" for this SKU/new part for the selected suppliers and enter in my estimated Qty needed.
Click "send" deliver it to the selected suppliers.
Wait for suppliers to respond with initial MSA agreements that contain their rate tables for part X at different quantities.
Review each and "sign & return" each of the MSA contracts from the suppliers.
Done with contracting phase.
Supplier context: I manufacture newly developed Part X. I know my volume capabilities and have rate tables I can provide to prospective buyers.
Add my company global Registry (during Radish setup).
Add new Part X to my system, publish Part X to my global registry entry.
Wait for an RFQ from a buyer.
New RFQ request comes in from Buyer for Part X.
I reply to RFQ with a pre-signed MSA contract that includes my rate table.
Wait for Buyer to sign.
I am notified when buyer signs.
Done contracting phase.
Buyer context: We have an MSA with two suppliers for part X. It's now time to order the part so we can have the inventory we need to begin manufacturing.
Select from a list of my parts, the new part X for product Y.
With the part selected, create a new PO and allow me to enter the Qty/delivery dates I need.
Since this part has two contracted suppliers (from contracting phase), I can see my PO total price based on the MSA I have with each supplier, and any existing PO's I have sent are calculated into my rate.
Send PO to selected suppliers.
Wait for suppliers to accept the PO and update the PO status to "in fulfillment."
Wait for invoice.
Receive invoice from suppler, open it, and click "pay."
This PO is now completed/closed. Other POs could be still open, I am able to view the status of those.
Supplier context: We have an MSA for Part X with a Buyer. At this point I am just waiting for POs. Also, I am such a good supplier that I can always meet customer qty and time frame demands so I accept every PO I receive.
Receive notification of new PO from buyer.
Acknowledge the PO and change the PO state to "in fulfillment."
Go do the work of fulfilling the order for Part X.
Order filed, find the PO and create an invoice against it. The details are pulled from the PO.
Satisfied with the Invoice I click 'send' to deliver the invoice to the Buyer.
I wait to be paid.
I am notified when the buyer pays.
PO/Invoice phase completed.
Here are a few visualizations of how the Radish34 POC functions.
The figure below depicts a representational workflow, for the process of creating an MSA (Master Service Agreement). Refer to the Radish34 Workflow explainer, for a detailed context of the process below. This process is chosen as it addresses key interactions of the Radish34 API (built as a single tenant) with the backend microservices: ZKP, and Messenger. In addition, this process also demonstrates all the system interactions (functional view) of a procurement process (MSA) that are designed and implemented in the overall stack.
Below is a summary of the MSA workflow broken down by steps, and each step can be represented as a sequence of tasks - defined as any process interaction that is from the API container to the other containers. Please note that, a few aspects of the diagram below are still in development (particularly around the orchestration of the API services using a lightweight queue management library, "BullJS"). In the current version, only the interaction with the Messenger service is considered as a task, and efforts in the development branch depict our attempts to further modularize the key interactions, that could be modified or substituted with other custom plugins/modules. Throughout the process, any successful interaction is stored/logged on a mongo instance corresponding to each entity. There are 2 entities in this representation: Buyer (sender) and Supplier (recipient). Each entity is a separate instance of the following scale set of microservices: API, Messenger, DB (Mongo and Redis) per entity, and common microservices: UI and ZKP.
Buyer API executes methods to sign the MSA metadata under the babyjubjub scheme. This requires storage of the keys created for signing the MSA metadata, which is demonstrated to be managed locally on a development setup. From a practical standpoint, this is left to the best practices that are custom for each production setup and maintenance policies. The signed document, then is sent via the Messenger service to the supplier Radish34 instance from the buyer's instance.
Upon receiving the MSA metadata, the Supplier API extracts the signed metadata obtained via Messenger (and thereafter stored in the Supplier db instances), signs the metadata and sends back the "co-signed" document back to the buyer via Messenger (and thereafter stored in the Buyer db instances)
Buyer API then interacts ZKP service, to generate an offchain proof of execution of business logic: verify the signature of the supplier, and data validation checks on the terms of the MSA document, the volume tiering structure. This proof is then verified on chain, by invoking an RPC request to interact with the Shield and Verifier contracts deployed on chain. Buyer API communicates the successful verification (transaction hash), merkle leaf index (indicating the position in the merkle tree in the Shield contract, where the hash of the MSA document is stored on chain) to the Supplier via the Messenger service
Upon receiving the verification data from the Buyer, Supplier API could either run a confirmation check - either as extension to capture events emitted on chain during storage of hash in the merkle tree OR as an additional method to validate against data stored on the Supplier DB instance.
The figure below depicts Baseline as a set of microservices that are enabled using Baseline protocol. Radish34 is an instance of Baseline built for the procurement use case. Baseline has been formulated based on core design and product principles that are directional for Radish34 and any other customization of the Baseline protocol. Also shown is a sample instantiation of a hosted (assumed Microsoft Azure Services) application of a Baseline protocol.
The figure shows the various components of the Radish34 system. In line with the design and extensibility aspects set up in the Baseline protocol, the system architecture below also contains the components that can be replaced or modified for other similar use cases. Across the different services/integrations listed below, light green represents the components that can be replaced/modified and the darker ones represent the components that can be re-used for further customizations for similar use cases.
API: This microservice orchestrates the overall application management, and contains components that enable UI (GraphQL), blockchain, ZKP, messenger, and data integrations. In particular, API orchestration is also handled using queue management based approach.
Application Service: This represents the user facing or user interaction layer. Although the Radish34 demo shows a particular UI representation, this can be extended or integrated into external legacy data or application systems
Smart Contract Management Service: Radish34 smart contracts are managed and built as part of the deployment process. This could be customized as needed as part of an overall pipeline or can be handled on demand.
Zero Knowledge Service: Radish34 circuits represent the off-chain proofs/statements that are to be verified on chain. The service contains utilities for compiling circuits, generating keys for proof generation, generating proofs and verifier contracts
Messaging Service: Message communication is handled using Whisper, and the service also contains utilities for creating identities and pub/sub wrappers for handling message communication
Data Integration Service: This layer represents the different db components used in the Radish34 implementation to manage data across the storage instances (Mongo DB) and cache instances (Redis DB)
Additional integrations:
Custom wallet (in the form of config files) are leveraged by the API and Blockchain interaction components to transact on chain. The config files are loaded as part of the build process, and contain key metadata required for the overall application user configuration settings
Public mainnet integrations are handled through the API to in turn invoke RPC calls to the ethereum mainnet
This document provides a description of the procurement use case as an example/show case of utilizing the public ethereum mainnet for conducting ongoing procurement operations within the constraints of privacy and established baseline requirements to develop a scalable, repeatable, and extensible pattern for enterprises.
Based on discussions around scoping and observing general patterns in the procurement industry, a 2 party system of a buyer who intends to procure goods and a supplier (manufacturer), who can provide the finished goods in exchange for a payment. The key interactions between these 2 parties across the process flow is laid out below.
RFP (Request for Proposal):
Buyer places request for proposal inviting suppliers to participate in the procurement process and lays out the procurement needs (quantity, price, etc.).
Supplier views the RFP.
Proposal:
Supplier upon receipt of an RFP, responds back to provide a proposal effectively providing the terms by which the supplier can satisfy the procurement needs of the buyer, privy only to the buyer. As an example, we assume that these terms are a volume discount tiering structure to determine the price of an order.
Buyer views the details of the proposal.
Contract (Master Service Agreement):
Buyer uses the terms of the proposal to award a contract or an MSA to the supplier based on the proposal from supplier, and privy only to the supplier.
Supplier views the agreement, signs the agreement, and provides the signed agreement back to the buyer.
Buyer validates and confirms the agreement.
Purchase Order:
Buyer issues a purchase order to the supplier, privy only to the supplier. Buyer may choose to place an order for any requested quantity in the bounds of the MSA terms. Additionally, the terms of the MSA are used to calculate the price of a given purchase order.
Supplier views the purchase order.
All 2 party interactions are meant to be strictly privy between the parties in interaction.
Data associated with the business process that is legacy to enterprises is never used directly to interact with the blockchain platform.
Complex interactions such as negotiations between the 2 parties for any of the above processes are left out of scope of this use case coverage.
For this use case, it is assumed that RFP occurs prior to MSA, even though in reality this order varies based on the parties in interaction and other potential related terms and conditions of the agreement process.
RFP in some industries can be publicly distributed amongst multiple suppliers to avoid unfair advantage for one versus the other supplier (for example, in government use cases).
Corresponding to the above breakdown of the processes, below is a listing of technical - design/implementation implications based on the process overview and the assumptions. Moreover, the design of the system allows for a gradual build up of architectural components as we proceed from RFP to MSA to PO
RFP: Private communication of the RFPs is done via a secure off-chain communication channel.
Proposal: In reality, there may be terms associated with accepting proposals or determining them valid or not. For this use case, we assume that there is no on-chain validation of an RFP.
MSA: Co-signing of the documents is a pre-requisite for storing a hash of an MSA on chain. In addition, this process of signing should also ensure that the identity of supplier is never revealed on chain. This is done so by using ZKP (zk-SNARK) tooling, and the proofs generated off-chain that verify that the intended supplier has signed the MSA, are verified on-chain.
PO: Leveraging the terms of the MSA, a PO is created such that the inputs used to determine the price of the PO are never revealed, but can be verified on-chain using ZKP technologies like zk-SNARK.
During the initial RFP stage, there is an onset of pure off-chain communication. When in the MSA stage, Mainnet is leveraged for notarization and traceability. Finally, in the PO stage, verifiable off-chain computation provides a trigger to an on-chain process that issues POs as tokens.
The figure below describes a particular aspect of creating an MSA, and represented as a sequence diagram.
These context specific top level business objects such as RFP, MSA Contract, PO, and Invoice are loosely coupled and only contain external reference to other objects in the previous process flow. This is because it is possible to create any of these on their own (technically speaking) depending on the Organizations role and/or phase of interaction with other organizations in the Radish network. However, the application process management logic will re-enforce the proper creation order. It is expected that these objects cross system boundaries and also have on-chain representation. These objects are prominent in the User Interface and the end user can interact with them.
These object are supporting generic business contexts and the usage of the Radish system in an organization. They are required to run the Radish system but any on-chain identity is managed externally to the object (internally to the local system). These objects do NOT cross system boundaries and (other than account/identity used for messaging or on-chain transactions) do not have on-chain representation. These objects are likely reflected in the UI and the end user can interact with them, though potentially under different labels (eg User object is managed under "Account").
These objects are specific to the technology implementation. They encapsulate the delivery of objects, messages, data identity, etc... and help ensure reliability of the system as a whole and durability of the data. These objects are not indented to be used/interacted with by end-users (but could be for diagnostic purposes).
These support the direct operation of the Radish system as it is installed for a specific environment/deployment in an organizations data center/cloud. Cryptographic keys are stored separately from configuration to support separate access controls and key rotation. These objects need not be managed in an RDMS or storage system. Cryptographic keys, however, should be stored in a HSM based vault of some kind.
The original demo that led to the Baseline Protocol
Radish34 is the result of a 2019 joint development effort to build a supply chain POC. The work led to the Baseline Protocol, a way for enterprises to use the as without compromising corporate information security practices. Radish34 remains the best way to show the general baseline approach in a specific example. You can build and run the proof of concept . And you can see how a set of companies would integrate their supply chain management systems in this .
Supply chain, as a topic, presented an obvious choice for exploring ways to use public blockchain in business. In particular, key steps in the manufacturing procurement process were a good focus for the Radish34 project.
First, the team from EY that helped start the Radish34 project are experts on the subject and were able to articulate a highly precise and detailed set of workflows with both functional and non-functional requirements.
Second, supply chain has been a classic starting point for enterprise blockchain explorations, because it involves such a tangle of different entities that must work together. But, one of the key problems with using private or public blockchains in a supply chain context is .
Even when different companies are partners in a single supply chain, there are things Party A shouldn't know about the relationship or activities of Parties B and C, even if those activities support the same Workflow for the same set of goods. The Radish34 team had to find a way to coordinate companies without anyone that was maintaining the integrity of the ledger learning anything about the business activities or relationships of the participants.
It turns out, ironically, that this problem is more insidious for private blockchains than for public networks, given the relative ease of analysis an attacker with access to a node can perform on a small group of known counter-parties. And so the choice was to show how the public Ethereum network could be used in a confidential procurement scenario without anyone being able to analyze the ledger and learn about the cadence, volume or particulars of any Party's business.
Even with modern supply chain management (SCM) and order management systems, revenue recognition for a Supplier can take time. Take the case of a Buyer and a Supplier that agree to a volume discount arrangement, a tiered pricing table in their master service agreement (MSA). To keep it simple, imagine that the Supplier will give a 10% discount on orders over 100 units purchased over the next year. The first purchase order (PO) comes in for, say, 100 units. This is easy to calculate. The initial state of the agreement is zero -- no units yet ordered. No discount. After the PO is processed, the new state is 100. The next PO comes in for 100, and if everything goes right, the Buyer will receive 10% on each of those 100 units, because they all fall within the 10% discount tier. So far so good. But what if two POs come in at the same time and both calculate from a base of zero. This happens quite a lot in the real world. And it is one of the reasons why generally accepted accounting principles (GAAP) have rules about when a Supplier can recognize revenue from purchase activity. Until someone can go through and make sure that each PO calculated in the right order from the right starting position, there’s no way to be certain that the Buyer doesn’t owe more (or less) than what the Supplier thinks.
The Radish34 POC demonstrates how to ensure that each PO executes faithfully and in correct order (without double-execution from the same starting state) by using the Ethereum public network as the common frame of reference needed to be sure of what the Buyer owes more quickly. It does this without putting any of the Supplier or Buyer's data or running the shared code that executes the volume discount agreement of the MSA, and ensures that each PO is calculated faithfully against it, on any blockchain.
Instead, Radish34 implements the approach now called the Baseline Protocol. The public Mainnet is used not as a "single source of truth" (where the shared data is stored and the shared business logic is executed) but instead as a common frame of reference that enables the Supplier and Buyer to maintain their own systems of record in a verified state of consistency.
Even though this approach does not move the sensitive business data of the Buyer and Supplier's MSAs and POs to any kind of blockchain -- leaving it all right where any conservative security officer wants it, in their own internal high-security systems -- it does use the Mainnet's ability to store state and execute functions to provide this middleware service between the counterparties with great utility. And to be clear, while the approach uses well-known components such as peer-to-peer messaging, digital signatures, hashing, and zero-knowledge proofs, it’s how these elements work together that takes this from a simple "proof of existence" approach to something that can be used as a state marker, flow controller and "stealthy" private token for complex business processes in a widely distributed system environment.
The techniques used to work on the volume discount problem have other applications across the supply chain. Here are several that can reuse, more-or-less the same components and patterns as Radish34's demo Workflow, like a box of Legos, to construct solutions across the supply chain from end to end.
Say a Buyer wishes to make the same request for proposal (RFP) to 10 different suppliers. It may be desirable, or even mandatory, for the suppliers to know about the presence of the others in the RFP process and know that the same RFP was made to all of them. But it would not be appropriate for Supplier A to have access to Supplier B's bid. In fact, Supplier A shouldn't even be aware that any of the other suppliers actually bid on the RFP, even though an ideal system would link each bid verifiably to the original multi-party RFP.
The terms that govern the movement of a shipment of product from, say, a Manufacturer to a Wholesaler are usually not only confidential...their existence is confidential. And likewise, the terms between the Wholesaler and a Retailer of that product can't, in some cases, be known to the Manufacturer. However, there are cases when some or all of the product must be returned to the Manufacturer from the retail channel. Especially in highly regulated industries, the product's serialization process requires tight coordination. When the product is put back into circulation, the Retailer may need to coordinate with the Manufacturer. In this scenario, the Retailer has no visibility or connection past the Wholesaler. If this were only a "three party" problem, the Wholesaler in the middle could be used to join the two Parties on each side, but in many real-world scenarios, there are more Steps and more Counterparties involved.
In this case, what's needed is a way to ensure the overall integrity of a Workflow and run complex business rules that can connect Counterparties only when appropriate, without Parties necessarily having any awareness of the Steps that don't directly involve them. Each Party must be confident that what is coming into their Step is correct, and that what happens downstream from their activity will proceed correctly.
This is a trivial problem if a common vendor is trusted by everyone to run things. But this historically leads to balkanization as many vendors, smelling profits, convince different sets of companies to use them as the common frame of reference. Another way to handle this is to set up a consortium and jointly invest in a shared ledger solution, however, this doesn't solve the problem of the double-blind requirement for any of the firms maintaining a node that validates activities on that ledger. Even if those activities are encrypted and masked, maintainers will inevitably see that some kind of activity is happening, and that itself may give them strategic information that other participants wouldn't knowingly permit. This is particularly acute within a ledger used by a relatively small number of known companies.
Say a Supplier happens to make a product that competes with a company that not only makes products but also runs a shipping operation. If the Supplier is obliged to use the competitor for shipping to the Buyer, and if they have committed to a late-delivery discount, then it’s important for the Supplier to get the verified delivery date from the Shipper. If the Shipper knows who the Supplier is (so that it can send them the delivery date), then they can use that information to know a lot about their product's competition: volumes, peak-and-troughs, and their customer base. What if the Shipper were only aware of its Step in the Workflow. What if, short of opening up a shipping box and inspecting the item, the Shipper didn’t know who was shipping the package to that address? The trick then is getting the delivery date to the Shipper without knowing where to send it. This is where having a common frame of reference, a message bus, is useful. The Shipper can 'dead-drop' the date and a topic (a key-value-pair). The Supplier can watch the topic and grab the date. This is a good use of a public Mainnet, if we can use it without leaving traces that others could use to discover and analyze the Supplier, Buyer or Shipper's activities.
With the release of Baseline Protocol v0.1, much of the original Radish34 proof of concept has been altered, abstracted, generalized or deprecated. We include the work here for legacy and so that the history of the protocol can continue to be examined in the future. Also, the use case described below continues to be a good explanation of a use case that can benefit from baselining.
Radish34 is the result of a 2019 joint development effort to build a supply chain POC. The work led to the Baseline Protocol, a way for enterprises to use the Mainnet as middleware without compromising corporate information security practices. Radish34 remains the best way to show the general baseline approach in a specific example. You can build and run the proof of concept . And you can see how a set of companies would integrate their supply chain management systems in this .
Supply chain, as a topic, presented an obvious choice for exploring ways to use public blockchain in business. In particular, key steps in the manufacturing procurement process were a good focus for the Radish34 project.
First, the team from EY that helped start the Radish34 project are experts on the subject and were able to articulate a highly precise and detailed set of workflows with both functional and non-functional requirements.
Second, supply chain has been a classic starting point for enterprise blockchain explorations, because it involves such a tangle of different entities that must work together. But, one of the key problems with using private or public blockchains in a supply chain context is compartmentalization.
Even when different companies are partners in a single supply chain, there are things Party A shouldn't know about the relationship or activities of Parties B and C, even if those activities support the same Workflow for the same set of goods. The Radish34 team had to find a way to coordinate companies without anyone that was maintaining the integrity of the ledger learning anything about the business activities or relationships of the participants.
It turns out, ironically, that this problem is more insidious for private blockchains than for public networks, given the relative ease of analysis an attacker with access to a node can perform on a small group of known counter-parties. And so the choice was to show how the public Ethereum network could be used in a confidential procurement scenario without anyone being able to analyze the ledger and learn about the cadence, volume or particulars of any Party's business.
Even with modern supply chain management (SCM) and order management systems, revenue recognition for a Supplier can take time. Take the case of a Buyer and a Supplier that agree to a volume discount arrangement, a tiered pricing table in their master service agreement (MSA). To keep it simple, imagine that the Supplier will give a 10% discount on orders over 100 units purchased over the next year. The first purchase order (PO) comes in for, say, 100 units. This is easy to calculate. The initial state of the agreement is zero -- no units yet ordered. No discount. After the PO is processed, the new state is 100. The next PO comes in for 100, and if everything goes right, the Buyer will receive 10% on each of those 100 units, because they all fall within the 10% discount tier. So far so good. But what if two POs come in at the same time and both calculate from a base of zero. This happens quite a lot in the real world. And it is one of the reasons why generally accepted accounting principles (GAAP) have rules about when a Supplier can recognize revenue from purchase activity. Until someone can go through and make sure that each PO calculated in the right order from the right starting position, there’s no way to be certain that the Buyer doesn’t owe more (or less) than what the Supplier thinks.
The Radish34 POC demonstrates how to ensure that each PO executes faithfully and in correct order (without double-execution from the same starting state) by using the Ethereum public network as the common frame of reference needed to be sure of what the Buyer owes more quickly. It does this without putting any of the Supplier or Buyer's data or running the shared code that executes the volume discount agreement of the MSA, and ensures that each PO is calculated faithfully against it, on any blockchain.
Instead, Radish34 implements the approach now called the Baseline Protocol. The public Mainnet is used not as a "single source of truth" (where the shared data is stored and the shared business logic is executed) but instead as a common frame of reference that enables the Supplier and Buyer to maintain their own systems of record in a verified state of consistency.
Even though this approach does not move the sensitive business data of the Buyer and Supplier's MSAs and POs to any kind of blockchain -- leaving it all right where any conservative security officer wants it, in their own internal high-security systems -- it does use the Mainnet's ability to store state and execute functions to provide this middleware service between the counterparties with great utility. And to be clear, while the approach uses well-known components such as peer-to-peer messaging, digital signatures, hashing, and zero-knowledge proofs, it’s how these elements work together that takes this from a simple "proof of existence" approach to something that can be used as a state marker, flow controller and "stealthy" private token for complex business processes in a widely distributed system environment.
The techniques used to work on the volume discount problem have other applications across the supply chain. Here are several that can reuse, more-or-less the same components and patterns as Radish34's demo Workflow, like a box of Legos, to construct solutions across the supply chain from end to end.
Say a Buyer wishes to make the same request for proposal (RFP) to 10 different suppliers. It may be desirable, or even mandatory, for the suppliers to know about the presence of the others in the RFP process and know that the same RFP was made to all of them. But it would not be appropriate for Supplier A to have access to Supplier B's bid. In fact, Supplier A shouldn't even be aware that any of the other suppliers actually bid on the RFP, even though an ideal system would link each bid verifiably to the original multi-party RFP.
The terms that govern the movement of a shipment of product from, say, a Manufacturer to a Wholesaler are usually not only confidential...their existence is confidential. And likewise, the terms between the Wholesaler and a Retailer of that product can't, in some cases, be known to the Manufacturer. However, there are cases when some or all of the product must be returned to the Manufacturer from the retail channel. Especially in highly regulated industries, the product's serialization process requires tight coordination. When the product is put back into circulation, the Retailer may need to coordinate with the Manufacturer. In this scenario, the Retailer has no visibility or connection past the Wholesaler. If this were only a "three party" problem, the Wholesaler in the middle could be used to join the two Parties on each side, but in many real-world scenarios, there are more Steps and more Counterparties involved.
In this case, what's needed is a way to ensure the overall integrity of a Workflow and run complex business rules that can connect Counterparties only when appropriate, without Parties necessarily having any awareness of the Steps that don't directly involve them. Each Party must be confident that what is coming into their Step is correct, and that what happens downstream from their activity will proceed correctly.
This is a trivial problem if a common vendor is trusted by everyone to run things. But this historically leads to balkanization as many vendors, smelling profits, convince different sets of companies to use them as the common frame of reference. Another way to handle this is to set up a consortium and jointly invest in a shared ledger solution, however, this doesn't solve the problem of the double-blind requirement for any of the firms maintaining a node that validates activities on that ledger. Even if those activities are encrypted and masked, maintainers will inevitably see that some kind of activity is happening, and that itself may give them strategic information that other participants wouldn't knowingly permit. This is particularly acute within a ledger used by a relatively small number of known companies.
Say a Supplier happens to make a product that competes with a company that not only makes products but also runs a shipping operation. If the Supplier is obliged to use the competitor for shipping to the Buyer, and if they have committed to a late-delivery discount, then it’s important for the Supplier to get the verified delivery date from the Shipper. If the Shipper knows who the Supplier is (so that it can send them the delivery date), then they can use that information to know a lot about their product's competition: volumes, peak-and-troughs, and their customer base. What if the Shipper were only aware of its Step in the Workflow. What if, short of opening up a shipping box and inspecting the item, the Shipper didn’t know who was shipping the package to that address? The trick then is getting the delivery date to the Shipper without knowing where to send it. This is where having a common frame of reference, a message bus, is useful. The Shipper can 'dead-drop' the date and a topic (a key-value-pair). The Supplier can watch the topic and grab the date. This is a good use of a public Mainnet, if we can use it without leaving traces that others could use to discover and analyze the Supplier, Buyer or Shipper's activities.