NextGate Product Ecosystem — Architecture & Purchase Flows
Overview
NextGate's e-commerce layer handles two fundamentally different kinds of products: physical products (tangible goods that require shipping and delivery confirmation) and digital products (files that a buyer downloads). Both types share the same payment infrastructure, checkout session system, and financial rails — but diverge completely at the fulfillment stage.
1. Product Types
Physical Products
A physical product has real-world stock. The platform tracks inventory, holds it during checkout, ships it through a seller, and releases escrow only after the buyer confirms physical receipt. The entire lifecycle can take days or weeks.
Digital Products
A digital product is a file (or collection of files) that the seller uploads to a private, access-controlled storage bucket. There is no shipping. There is no inventory. There is no confirmation code. The moment payment clears, the buyer can download. Escrow releases immediately. The lifecycle is measured in seconds.
A single product can be either physical or digital — never both. The productType field on the product record is the authoritative signal that drives every downstream decision.
2. Digital Products Have No Inventory
Key rule: Digital files do not deplete. Inventory tracking is bypassed entirely for digital products at every stage.
Because of this, the following are all skipped for digital products:
- No inventory hold at checkout session creation
- No stockQuantity check on add-to-cart or at checkout
- inventoryHeld is always false for digital sessions
- holdInventory() and releaseInventory() calls are skipped
- isInStock() and canOrderQuantity() always return true
The only "quantity" concept that applies to digital products is the seller's optional participant cap on group purchases — for example, capping a cohort-based online course at 50 students. This cap lives on the group instance as totalSeats and represents a business rule, not a stock constraint. No inventory system is involved.
3. How Sellers Prepare Digital Products
Seller → Request presigned upload URL
→ Platform generates time-limited URL (MinIO private bucket)
→ Seller uploads file DIRECTLY to MinIO (API server bypassed)
→ Seller confirms upload to API
→ Platform records file metadata and links to product
A product can have multiple files. Each gets its own record. Buyers get access to all files on purchase.
Sellers configure download rules per product:
- Expiry window → days after purchase links stay active (default: 7 days)
- Download cap → max downloads per buyer (default: unlimited)
- Clock start → expiry starts at purchase time OR at first download
4. The Cart
The cart is a persistent bag of products. It does not distinguish between physical and digital items — both coexist freely. It has no concept of stock, expiry, or fulfillment.
The physical/digital split only becomes relevant at checkout session creation.
5. Checkout Session Types
Every purchase flows through a checkout session — a short-lived record holding purchase intent before payment. All four session types work for both physical and digital products.
| Session Type | Description |
|---|---|
REGULAR_DIRECTLY |
Single-item purchase from the product page |
REGULAR_CART |
Multi-item purchase from a cart |
GROUP_PURCHASE |
Coordinated group buy at a discounted group price |
INSTALLMENT |
Down payment now, remainder paid over time |
Sessions expire (typically 15–30 minutes) to prevent buyers from holding physical inventory without paying. For digital-only sessions, expiry is still enforced for payment integrity, but no inventory is at stake.
6. Shipping Logic
All items digital? → Skip shipping entirely. Cost = 0. No inventory hold.
Any item physical? → Shipping address + method required. Inventory held.
Mixed cart (physical + digital, same shop)?
→ Engine splits into TWO sessions automatically:
Session 1: physical items → shipping lifecycle
Session 2: digital items → download lifecycle
7. Payment Infrastructure (Shared by All Types)
Payment works identically regardless of product type:
Buyer wallet → debited
Escrow → credited (money held, not yet with seller)
Ledger entry → recorded (double-entry, full audit trail)
Tx history → updated for buyer
For installment purchases, only the down payment moves at session time. Each subsequent payment creates its own ledger entry.
Escrow is the control point. Physical → held until buyer confirms delivery. Digital → released immediately at order creation.
8. Post-Payment Fulfillment — The Core Split
Physical path
Payment completes
→ Order created [PENDING_SHIPMENT]
→ Seller notified
→ Seller ships → marks order SHIPPED
→ 6-digit confirmation code generated → sent to buyer
→ Buyer enters code in app
→ Escrow releases to seller
→ Order [COMPLETED]
Escrow is held the entire shipping period. The code is the handshake — seller cannot claim money without buyer confirming receipt.
Digital path
Payment completes
→ Order created [COMPLETED immediately]
→ Escrow released to seller immediately
→ DigitalDownloadAccess records created (one per file)
→ Buyer notified with download link
→ Buyer downloads within expiry window
No shipping. No confirmation code. Delivery = access records created.
9. Group Purchase — Physical vs Digital
Both product types support group purchase. The financial hold (escrow per participant) is identical in both cases. What differs is inventory and post-completion fulfillment.
Physical group purchase
Each participant pays → Escrow held + Inventory held per participant
Group fills → COMPLETED
→ Physical orders created for all participants [PENDING_SHIPMENT]
→ Each participant goes through shipping lifecycle individually
→ Each escrow releases on individual delivery confirmation
Group expires without filling → All escrows refunded
Digital group purchase
Each participant pays → Escrow held (NO inventory hold — digital has none)
Group fills → COMPLETED
→ Orders created for all participants [COMPLETED immediately]
→ All escrows released immediately
→ DigitalDownloadAccess records created for every participant
→ All buyers can download immediately
Group expires without filling → All escrows refunded (identical to physical)
The seller's participant cap (e.g. "max 50 students") is a business rule on the group instance — not inventory. No stock is involved.
10. Installment Purchase — Physical vs Digital
Both product types support installment. The payment schedule, ledger entries, agreement lifecycle, early payoff, and flexible payment features are identical regardless of product type. What differs is fulfillment timing — and for digital products, this choice carries real risk.
Fulfillment timing options
IMMEDIATE — order and access created after the down payment. Buyer gets the product now, pays over time.
- Physical: seller ships after down payment, takes risk on future payments.
- Digital: buyer downloads immediately. If buyer defaults, downloaded files cannot be revoked. Seller has no recourse.
AFTER_PAYMENT — order and access created only after the final payment clears.
- Physical: layaway model — seller holds stock, ships at the end.
- Digital: safest model — access never opens until fully paid. Default defaults are clean: access records simply never created.
Platform recommendation: AFTER_PAYMENT is the default for digital installment products. Sellers must explicitly opt into IMMEDIATE with acknowledgment that pre-delivery means no recourse on default.
On default — digital IMMEDIATE
Buyer stops paying → Agreement marked DEFAULTED
→ No new access records created for future files
→ Already-downloaded files cannot be revoked ← known limitation, seller accepts this risk
On default — digital AFTER_PAYMENT
Buyer stops paying → Agreement marked DEFAULTED
→ Access records never created
→ No content ever delivered ← clean, no recourse needed
11. The Download System
On every successful digital purchase (any session type, any fulfillment trigger):
Platform creates DigitalDownloadAccess record per file:
- buyer ID + order ID + file ID
- downloadCount (starts at 0)
- maxDownloads (null = unlimited, or seller-set cap)
- accessExpiresAt (now + expiry window)
- firstDownloadAt (set on first use)
On every download request:
Buyer hits authenticated endpoint
→ Check 1: Does buyer own an active access record for this file?
→ Check 2: Has expiry window passed?
→ Check 3: Has download cap been reached?
All pass → Platform generates presigned GET URL (5-min TTL)
→ Buyer browser downloads DIRECTLY from MinIO private bucket
→ Access record downloadCount incremented
→ API server is NOT in the file transfer path
The 5-minute TTL means a leaked URL is useless within minutes. The raw MinIO object key is never exposed to the buyer — only opaque access identifiers.
12. Scenario Walkthrough — All Combinations
Scenario A — Direct purchase, physical product
Buyer finds a T-shirt. Clicks "Buy Now".
REGULAR_DIRECTLY session created
→ Shipping address + method required
→ Inventory held
→ Buyer pays → Escrow funded
→ Order created [PENDING_SHIPMENT]
→ Seller ships → marks SHIPPED
→ 6-digit code sent to buyer
→ Buyer confirms → Escrow released
→ Order [COMPLETED]
Scenario B — Direct purchase, digital product
Buyer finds a PDF course. Clicks "Buy Now".
REGULAR_DIRECTLY session created
→ No shipping fields collected
→ No inventory hold
→ Buyer pays → Escrow funded and immediately released
→ Order created [COMPLETED]
→ 3 DigitalDownloadAccess records created (one per chapter PDF)
→ Buyer receives download link
→ Buyer downloads within 7 days
Scenario C — Cart, physical only, multiple shops
Phone case from Shop A + charger from Shop B.
REGULAR_CART session created
→ Inventory held for both items
→ Buyer pays once
→ Order engine groups by shop:
Order 1: Shop A [PENDING_SHIPMENT]
Order 2: Shop B [PENDING_SHIPMENT]
→ Each seller ships independently
→ Each escrow releases on individual buyer confirmation
Scenario D — Cart, digital only
Video course + design template pack.
REGULAR_CART session created
→ No shipping. No inventory hold.
→ Buyer pays once
→ Order 1: video course [COMPLETED] → 4 access records
→ Order 2: template pack [COMPLETED] → 2 access records
→ Buyer downloads all 6 files within 7 days
Scenario E — Cart, mixed physical + digital, same shop
Printed book (physical) + PDF supplement (digital), same shop.
Engine detects mixed cart → splits automatically:
Session 1: printed book → shipping lifecycle
Session 2: PDF → download lifecycle
Buyer sees one checkout flow, gets two orders in history:
Order 1 (book): [PENDING_SHIPMENT] → shipping → confirmation → escrow releases
Order 2 (PDF): [COMPLETED] → download access immediate
Scenario F — Group purchase, physical product
5 buyers collectively buy a speaker.
Buyer 1 initiates → GROUP_PURCHASE session → pays → group instance created (timer starts)
Buyers 2–5 join → each pays → inventory held per participant → escrow held
Group fills → COMPLETED
→ Physical orders created for all 5 [PENDING_SHIPMENT]
→ Each participant ships independently
→ Each escrow releases on individual delivery confirmation
Timer expires before filling:
→ All 5 escrows refunded
→ Inventory holds released
Scenario G — Group purchase, digital product
30 buyers join a cohort-based online course. Seller caps at 30 students.
Buyers 1–30 join → each pays → escrow held (NO inventory hold)
Seat cap is a business rule on the group instance — not stock
Group fills (30th seat) → COMPLETED
→ Orders created for all 30 [COMPLETED immediately]
→ All 30 escrows released immediately
→ DigitalDownloadAccess records created for every participant
→ All 30 buyers can download immediately
Timer expires before 30 seats fill:
→ All escrows refunded (identical to physical)
Scenario H — Installment, physical, IMMEDIATE fulfillment
Laptop, 6-month plan, 20% down, seller ships immediately.
INSTALLMENT session created
→ Inventory held
→ Down payment charged (20%)
→ Agreement created (6 scheduled payments)
→ Order created [PENDING_SHIPMENT] ← immediately after down payment
→ Seller ships
→ Monthly payments auto-process via scheduled jobs
→ Each payment: wallet debited → ledger entry
→ Seller carries risk if buyer defaults on future payments
Scenario I — Installment, physical, AFTER_PAYMENT fulfillment
Same laptop, but seller uses layaway model.
INSTALLMENT session created
→ Inventory held conceptually
→ Down payment charged
→ Agreement created (6 scheduled payments)
→ NO order created yet
→ Monthly payments auto-process
→ Final payment clears → Agreement COMPLETED
→ Order created [PENDING_SHIPMENT] ← only now
→ Shipping lifecycle begins
Scenario J — Installment, digital, AFTER_PAYMENT (recommended)
Video course library, 500,000 TZS, 3-month plan.
INSTALLMENT session created
→ No inventory hold
→ Down payment charged (30%)
→ Agreement created (3 scheduled payments)
→ NO order, NO download access created yet
→ Monthly payments auto-process
→ Final payment clears → Agreement COMPLETED
→ Order created [COMPLETED]
→ DigitalDownloadAccess records created ← only now
→ Buyer downloads
If buyer defaults before final payment:
→ Agreement DEFAULTED
→ Access records never created
→ No content ever delivered ← clean outcome
Scenario K — Installment, digital, IMMEDIATE fulfillment
Same course, but seller opts into IMMEDIATE.
INSTALLMENT session created
→ No inventory hold
→ Down payment charged (30%)
→ Agreement created
→ Order created [COMPLETED] ← immediately
→ DigitalDownloadAccess records created ← immediately
→ Buyer downloads now
Monthly payments continue auto-processing.
If buyer defaults:
→ Agreement DEFAULTED
→ Platform stops creating access for any new files
→ Already-downloaded files CANNOT be revoked ← seller accepted this risk
13. Escrow Behavior Summary
| Scenario | Inventory Held | Escrow Released |
|---|---|---|
| Physical — direct | Yes, at session creation | After buyer confirms delivery |
| Digital — direct | No | Immediately at order creation |
| Physical — group | Yes, per participant | After each participant confirms delivery |
| Digital — group | No | Immediately when group completes |
| Group — expired/failed | Released immediately | Refunded to all participants |
| Physical — installment IMMEDIATE | Yes, at session | Per installment via direct ledger |
| Physical — installment AFTER_PAYMENT | Yes, held until final payment | After final payment, order created |
| Digital — installment IMMEDIATE | No | Immediately after down payment |
| Digital — installment AFTER_PAYMENT | No | Immediately after final payment |
14. MinIO Bucket Architecture
nextgate-public (world-readable)
→ Product images, shop logos, profile pictures, category images
→ URLs are permanent, no expiry
nextgate-digital-content (private, no public access)
→ Paid digital product files only
→ Only accessible via presigned URLs (5-min TTL)
→ Generated by API after access verification
→ Raw object key never exposed to buyers
This separation ensures a seller can never accidentally expose a paid file by uploading to the wrong location.
15. Key Invariants
- Every money movement goes through the double-entry ledger.
No direct wallet balance adjustments exist.
- Escrow receives the full payment before any fulfillment action begins.
- Orders are never created before:
regular purchase → payment completes
group purchase → group fills
installment → fulfillment trigger (down payment or final payment)
- Digital products never participate in inventory holds.
Stock quantity checks are bypassed at every stage.
- Download links never expose the raw MinIO object key.
Only opaque access identifiers resolve to presigned URLs via authenticated API.
- A checkout session produces orders exactly once.
Idempotency checks prevent duplicates under retry or failure.
- Session expiry is enforced before payment processing.
An expired session cannot be paid.
- For digital installment IMMEDIATE: already-downloaded files cannot be revoked on default.
This is a known limitation. Sellers must explicitly accept it.
