Technical Implementation Plan

Igun Africa SaaS — Technical Implementation Plan

Last updated: 2026-09-16

Summary

Build the platform as a modular monolith with one PostgreSQL database, an event bus for side effects, and adapters for every third-party service. This keeps one deployable unit for a small team while leaving clean seams to split out services later (normalisation, notifications, documents).

The existing MVP stack is not described in the roadmap, so the stack below is a recommendation to be reconciled with what is already running on staging.

Principles

  1. Server-side authorisation everywhere: every query is scoped by company, role, permission and plan entitlement.
  2. Append-only by design: audit log, custody events, negotiation rounds and executed contracts are never updated or deleted.
  3. Explicit state machines for registration, requests, negotiations, trades, lots, contracts, engagements and disputes.
  4. Adapters over vendors: registry, KYC, e-signature, payments, FX/duties and vessel data sit behind interfaces, so a provider can change per country.
  5. Money and quantities are exact: decimal types, currency and unit stored with every value, FX rate snapshotted per transaction.
  6. Localisation from day one: i18n keys, RTL-aware layout, locale formatting.

System architecture

Three web front ends (customer app, admin portal, provider portal) call one API; the API writes to Postgres and emits domain events that background workers consume.

Domain modules inside the monolith

ModuleOwnsKey events emitted
IdentityUsers, sessions, MFA, team permissionsUserInvited, PermissionChanged
Company and KYCCompanies, roles, documents, verification, ESGRegistrationSubmitted, KycApproved
BillingPlans, entitlements, subscriptions, invoicesSubscriptionRenewed, PaymentFailed
CatalogueProduct specs, listings, CSV importListingPublished, ListingExpiring
InventoryLots, allocations, movementsLotAllocated, StockDecremented
RequestsRFQs, RFOs, quotations, offers, bidsRequestPublished, ResponseSubmitted
NegotiationRounds, counters, locks, acceptanceCounterProposed, ResponseAccepted
NormalisationParameter sets, FX/duty snapshots, comparisonsComparisonRun
TradeTrades, awards, delivery schedule, statusTradeCreated, TradeDelivered
ContractsTemplates, generation, signature, PDFsContractExecuted
Service providersDirectory, engagements, custody, assaysAssayUploaded, CustodyEventLogged
Settlement and disputesPrice adjustment, fees, payouts, disputesDisputeOpened, SettlementReleased
CRM and analyticsRelationships, references, ratings, read modelsRatingSubmitted
NotificationsPreferences, in-app, email, scheduled reminders
AuditAppend-only log
AdminStaff roles, impersonation, parameters, taxonomyAccountSuspended

Integration adapters

CapabilityNamed in sourceNotes
Company registryOrbis, OpenCorporates, government APIsPer-country strategy; fallback to manual compliance queue
KYC / identityOnfido, Jumio, TruliooProvider not yet chosen
E-signatureDocuSign (chosen)Webhooks drive contract status
Subscription paymentsFlutterwave (chosen)Tokenised cards, retries
Metal paymentsVerto (chosen)Global account, settlement, fee deduction
FX and dutiesXE, OANDA, Refinitiv, customs APIsRate locked at RFO creation
Vessel dataMarineTraffic, VesselFinder, project44Tracking on trade

Also needed (implied by the source, not in its vendor list)

  • Email and SMS delivery: email verification, password reset OTP, notifications and the SMS channel.
  • Large media: resumable uploads for videos up to 1GB, virus scanning, and CDN delivery.
  • QR/barcode: generating and scanning sample IDs for chain of custody.
  • CO2 data: emission factors (by commodity, transport mode, distance) for “platform-calculated” figures.
  • CSV pipeline: template download, validation with row-level errors, and background import for products.

Key flows handled carefully

  • Acceptance: a single transaction takes a row lock on the response (or uses an idempotency key), checks permission and entitlement, then creates the trade. This meets the “no two trades from one response” rule.
  • Inventory: allocation and decrement run in the same transaction as the trade state change, with a check that allocated quantity never exceeds available.
  • Expiry and reminders: a scheduler handles invitations (7 days), listings (3 days and 24h before), quotations, counters and RFO closing dates.
  • Assay to settlement: AssayUploaded triggers price recalculation from the contract formula; an open dispute blocks settlement release.

These are common, well-supported choices for this kind of platform; swap any layer for what the MVP already uses.

LayerRecommendationWhy
Front endReact + Next.js, TypeScriptMature i18n and RTL support; SSR for marketplace pages
UIComponent library with RTL support; logical CSS propertiesArabic layout without a separate stylesheet
i18nICU message format library + Intl APIPlurals, locale numbers, dates, currencies
APITypeScript (NestJS) or equivalent, REST + OpenAPIClear module boundaries, typed contracts
DatabasePostgreSQLTransactions, row locks, JSONB for ESG and spec attributes, row-level security
SearchPostgres full-text first; OpenSearch if marketplace search slowsAvoid an extra system early
Queue / jobsRedis-backed job queue, or a managed queueReminders, retries, webhooks, CSV imports
FilesS3-compatible storage + antivirus scan on uploadSigned, expiring URLs
PDFsHTML-to-PDF renderer on workersContracts, comparisons, invoices
RecommendationsRules + weighted scoring first; ML later once trade data existsNot enough data at launch for a trained model
AnalyticsRead models / materialised views in PostgresSeparate from transactional queries
InfraContainers on a managed cloud, IaC, CI/CDRegion picked after data-residency decision
ObservabilityStructured logs, metrics, tracing, error trackingPer-view latency budgets from the NFRs

Core data model

Everything hangs off Company; a Trade is the hub that links requests, contracts, lots, providers and settlement.

EntityKey fieldsNotes
Companylegal name, reg. number, country, TIN, verification statusHas CompanyRole rows (buyer, supplier, provider)
CompanyRolerole, plan, entitlements, KYC statusSeparate subscription per role
User / Membershipemail, MFA, locale; permissions per companyAt least one admin enforced
Documenttype, file, expiry, verification status, visibilityCertificates, licences, KYC, trade docs
RegistrationDraftsection data (JSONB), last savedResumable onboarding
Invitationinviter, invitee email, request ref, expires_at, status7-day expiry
ProductSpecmetal type, form, grade, moisture, origin, mediaArchive, not delete, when referenced
Listingspec, qty, UoM, MOQ, price, currency, Incoterm, port, validityLinks to lots
Lot / LotMovementspec, qty, location, status; movement actor, reason, tradeMovements append-only
Requesttype (RFQ/RFO), intent, mode, audience, closing date, locked fields, CO2 source, FX snapshotDelivery schedule for RFQs
Responsetype (quote/offer/bid), terms, validity, status
NegotiationRoundauthor, changed terms, validity, round numberAppend-only; max 2 per party
ComparisonRunparameter set version, rates used, resultsReproducible past decisions
Trade / Awardparties, qty, terms, parent request, statusOne per award in split RFQs
Contracttemplate version, status, signatories, PDFImmutable once executed
ProviderEngagementprovider, service type, payer rule, status, comments
Sample / CustodyEventsample ID, handler, time, place, photo, signature hashHash-chained
AssayResultstructured values, lab, custody IDDrives price adjustment
PriceAdjustmentbase price, formula, values, final priceFull audit
Disputesubject (assay/charge), steps, resolutionBlocks settlement
Settlement / Chargeamounts, brokerage fee, provider fees, payer, statusVia Verto
Rating / Reference / CrmNotecounterparty, trade, category; notes private
Notification / Preferencecategory, channel, read stateSecurity categories locked on
AuditLogactor, company, action, entity, before/after, time, impersonatorAppend-only, hash-chained

The tamper-proof requirement for custody and audit can be met with a hash chain (each row stores the hash of the previous) plus database permissions that forbid UPDATE and DELETE. A blockchain is not required for this.

Phased delivery plan

Five phases ordered by dependency. Durations are not given because team size and the MVP codebase are unknown; size each phase once those are confirmed.

PhaseScopeExit criteria
0. FoundationsPick the 6 third-party vendors; audit MVP code; auth, sessions, MFA; team permissions; audit log; notification service; i18n + RTL shell; CI/CD, environments, backupsA team member can be invited, permissioned, and every action is audited
1. Onboarding and billingSupplier + buyer registration with drafts; document upload and scanning; registry and licence verification with manual fallback; invitations; admin approval queue; supplier plans, entitlements, Flutterwave cards and renewals; admin portal v1A supplier and buyer can register, be approved, and pay for a plan
2. Trade coreProduct specs and CSV import; listings and expiry; RFQ upgrades (delivery schedules, split awards); RFO (intent, auction/negotiation, locked fields, CO2 source); quotations, offers, bids; negotiation with counter limits and safe acceptance; trade creation; contract templates + DocuSignA negotiated deal ends in an executed, signed contract
3. Fulfilment and settlementProvider onboarding and portal; lab and logistics selection; engagements; chain of custody with QR; structured assays and price adjustment; disputes; inventory lots and auto-decrement; Verto settlement, brokerage and provider feesA trade runs from contract to inspected, delivered, settled
4. IntelligenceOffer normalisation (FX, duties, freight, Incoterms); CRM, references, ratings; analytics and CO2 reporting; recommendations; Invite to DigitalBuyers compare landed costs in one click; dashboards live

Normalisation is placed in Phase 4 because it depends on FX/duty data contracts, but it is a key selling point; move it into Phase 2 if the data provider is ready early.

Heaviest areas to size carefully: inventory (the source flags it), normalisation, negotiation concurrency, and chain of custody.

Security, DevOps, risks and decisions

Security

  • Central policy layer checks company, permission and entitlement on every endpoint; add automated tests for CRM private notes, KYC visibility and provider data scoping (the source asks for explicit tests).
  • Encryption at rest for database and storage; field-level encryption for bank details and KYC identifiers.
  • Tokenised cards only (no card data at Igun); signed webhooks from DocuSign, Flutterwave and Verto.
  • Impersonation sessions are flagged in the UI, logged separately and shown to the customer.
  • Permission changes and session revocation take effect immediately (short-lived access tokens + server-side session store).

DevOps and quality

  • Environments: dev, staging, production; infrastructure as code; automated migrations.
  • CI runs unit, integration and permission tests; end-to-end tests cover the full trade flow and RTL layout.
  • Vendor sandboxes used in staging; adapters have fakes for local development.
  • Backups with scheduled restore drills; latency budgets tracked for search, comparison and analytics.

Risks

RiskImpactMitigation
Many African registries lack APIsSlow onboardingManual compliance queue with SLA; aggregator where coverage exists
E-signature legal validity varies by countryContracts challengedLegal review per jurisdiction before launch
FX/duty data gapsWrong landed costsShow “incomplete”, never guess; versioned parameter sets
Double acceptance or over-allocationDuplicate trades, oversold stockDB transactions, row locks, idempotency keys
Disputed assaysSettlement delays, liabilityHash-chained custody, photo evidence, second-lab workflow
Low data for recommendationsWeak matchesStart rule-based
Scope sizeDelaysPhase gates; reuse MVP where sound

Decisions needed before build

  • Confirm the current MVP stack and whether to extend or re-platform.
  • Select providers: registry, KYC, FX/duties, vessel data.
  • Hosting region and data residency.
  • Permission matrix and signature authority (compliance).
  • Uptime, recovery and performance targets.
  • Team size, to turn phases into a timeline.