Marketplace Architecture
HeritagePay marketplace is a contract-backed value-chain execution layer. It is not a generic listing catalogue and it is not a standalone mobile tab.
Architecture decision
Build the first marketplace version as a bounded context inside the existing backend. That keeps it close to Plane B auth, wallet identity, audit, document storage, webhooks, and Blnk-backed payment controls.
Keep these replaceable:
- Extraction worker.
- Proof anchoring adapter.
- Public marketplace portal.
Bounded contexts
| Context | Owns |
|---|---|
| Marketplace Registry | buyers, suppliers, contractors, verifiers, funders |
| Programmes | value-chain initiatives and opportunity groups |
| Opportunities | tenders, work packages, lots, eligibility |
| Contract Workspace | contract drafts, signed versions, hashes |
| Milestone Ledger | obligations, expected/completed counts, review state |
| Evidence Vault | photos, PDFs, reports, receipts, notes |
| Payment Controls | controlled release instructions into wallet/ledger |
| Payment Executions | provider-neutral gateway handoff attempts and settlement state |
Core flow
Code
Definition of integrated
Marketplace is integrated at spine level when an operator can create a
wallet-linked contract, assign programme/opportunity context, set participant
role, track milestone progress like 0/5, and set payment-control state while
the mobile user can see their assigned obligations.
The current product now has the first contract-vault spine plus a first marketplace registry and assignment path:
GET /internal/marketplace/programmesPOST /internal/marketplace/programmesGET /internal/marketplace/opportunitiesPOST /internal/marketplace/opportunitiesGET /internal/marketplace/participantsPOST /internal/marketplace/participantsGET /internal/marketplace/assignmentsPOST /internal/marketplace/assignmentsGET /internal/marketplace/milestonesPOST /internal/marketplace/milestonesGET /internal/marketplace/evidencePOST /internal/marketplace/evidenceGET /internal/marketplace/payment-controlsPOST /internal/marketplace/payment-controlsGET /internal/marketplace/payment-executionsPOST /internal/marketplace/payment-executionsPOST /internal/marketplace/payment-executions/provider-eventsGET /internal/contract-vault/versionsPOST /internal/contract-vault/versionsPOST /internal/contract-vault/versions/anchor-eventsGET /internal/contract-vault/signaturesPOST /internal/contract-vault/signaturesPOST /internal/contract-vault/signature-requests/provider-eventsGET /internal/contract-vault/commitmentsPOST /internal/contract-vault/commitmentsGET /internal/contract-vault/eventsPOST /internal/contract-vault/eventsGET /internal/contract-vault/extractionsPOST /internal/contract-vault/extractionsPOST /internal/contract-vault/extractions/decisions
Operators can create programmes, opportunities, participants, and participant
assignments in backoffice, then link contracts to those references from
Contract Vault. Operators can also create structured milestones with progress
such as 0/5 against an opportunity and optional contract reference, then add
or review evidence rows against those milestones. Evidence rows now include
attachment policy metadata such as provider, object key, byte size, attachment
status, visibility, retention policy, and verification timestamp; approved
file evidence requires a URI and SHA-256 checksum. Approved evidence can now be
linked to payment-control instructions, which record release eligibility and
operator approval without executing a money transfer by themselves. Approved
payment controls can now be followed by payment execution attempts, which store
the replaceable provider class, provider execution reference, attempt number,
status, timestamps, and safe response detail. Provider callbacks or reconciliation
runs can update those existing executions through the provider-events endpoint.
Backoffice exposes this from the Marketplace page as a manual provider-event
workflow, so operators can reconcile a gateway callback by provider execution
reference without starting a second payment.
When the linked payment control has a contract reference, each execution state
also appends a contract history event. This gives the marketplace a traceable
handoff trail without locking the product to one gateway or claiming automatic
settlement before a concrete provider-specific adapter exists.
Signature request provider-events follow the same rule for contract signing:
the core receives provider-neutral callbacks by provider request reference,
records the signer receipt, rolls version status forward, and keeps the concrete
signature vendor replaceable.
Backoffice can apply the same provider-event contract manually from Contract
Vault for operational reconciliation, without making the signature vendor a
hard dependency of the core module.
Contract version anchor-events do the same for proof anchoring: the core records
the proof hash, provider reference, vault/chain references, and contract
anchoring status without owning the eventual chain or vault adapter.
Backoffice operators can record and review those anchor receipts from Contract
Vault, so the external writer can remain modular while the operator surface
still shows what has been anchored.
The next marketplace layer is not another listing screen. It is the structured
contract workspace. Three pieces are now present: contract versions, which
store the exact SHA-256 proof for a draft or signed contract version; signature
requests, which create a provider-neutral ceremony boundary before any provider
callback exists; signature provider-events, which reconcile callbacks from a
replaceable provider into signer receipts; signature receipts, which roll up
signer-by-signer ceremony state onto the version; and contract commitments, which store measurable points such as
0 / 5 restaurants that can be created manually or posted by an extractor
service. Extraction runs now provide the side-service intake boundary: the core
stores the run and proposed commitments, while the extractor remains
replaceable. Operators can accept or reject extraction runs after review, which
turns the proposed points into an explicit follow-up set without giving the
extractor ownership of the contract record. The remaining pieces are concrete
signature provider verification adapters, an external anchoring worker, and external gateway
verification adapters for payment executions. Contract events are the append-only
bridge for those modules: extractor runs, signatures, evidence receipts,
payment-control decisions, and payment executions already append timeline
entries without mutating the contract proof itself. Anchors and concrete
provider callbacks should use the same event spine.