Developer Docs

Beta Readiness Checklist

Audience: Internal platform engineers preparing for the Family & Friends beta launch.

This document is the single source of truth for beta readiness. Before testers arrive, every engineer should understand the architecture, core user flows, known limitations, and what happens during key lifecycle events.


1. Architecture at a Glance

Mallnline is a federated GraphQL platform with 17 subgraphs composed via Hive Gateway into a single supergraph (~525K characters of SDL).

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    ngwenya-gateway :30000                        โ”‚
โ”‚            Hive Gateway  ยท  Federation v2.9  ยท  525K SDL        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚maletsโ”‚prods โ”‚servs โ”‚ucart โ”‚media โ”‚blogs โ”‚comms โ”‚  + 7 NestJS   โ”‚
โ”‚:3001 โ”‚:3004 โ”‚:3003 โ”‚:3005 โ”‚:3006 โ”‚:3007 โ”‚:3016 โ”‚  subgraphs    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚    auth     โ”‚   uchat     โ”‚    scim     โ”‚ intelligence (Rust)  โ”‚
โ”‚   :3008     โ”‚   :3017     โ”‚   :3019     โ”‚   :3026              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  postgres   โ”‚   redis     โ”‚   mongo     โ”‚ meilisearch โ”‚conduit โ”‚
โ”‚   :5432     โ”‚   :6379     โ”‚  :27017     โ”‚    :7700    โ”‚ :8448  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Subgraph Registry (17 total)

# Subgraph Port Technology Purpose
1 malets 3001 NestJS Storefront management, ownership, verticals
2 services 3003 NestJS Bookable services, schedules, add-ons
3 products 3004 NestJS Product catalog, variants, inventory
4 ucart 3005 NestJS Shopping cart, multi-malet aggregation
5 media 3006 NestJS File uploads, image editing, Cloudflare R2
6 blogs 3007 NestJS Blog posts, publishing workflow
7 auth 3008 Rust (Axum) OIDC, passkeys, OTP, social login
8 nodes 3009 NestJS User profiles, handles, follows, social graph
9 organizations 3010 NestJS Teams, RBAC, invitations, audit
10 murchases 3013 NestJS Orders, fulfillment, workrooms, tracking
11 payments 3014 NestJS Stripe, subscriptions, invoice, tier enforcement
12 search 3015 NestJS Full-text search, facets, trending
13 community 3016 NestJS Q&A, reviews, discussions, moderation
14 uchat 3017 Rust (Axum) End-to-end encrypted messaging
15 alerts 3025 NestJS Email/SMS/in-app notifications, WS subscriptions
16 scim 3019 Rust (Axum) SCIM 2.0 directory provisioning (REST only)
17 experiences 3020 NestJS 13 vertical experience modules

Infrastructure

Service Port Purpose
PostgreSQL 5432 Auth, uChat, SCIM databases
MongoDB 27017 All NestJS subgraph data
Redis 6379 Response caching, APQ, rate limiting, WS presence
Meilisearch 7700 Search index (products, services, malets, blogs)
Conduit 8448 Matrix homeserver for uChat E2E encryption

Cross-service communication: TCP microservices (NestJS ClientProxy) for payments, alerts, and nodes. Events are fire-and-forget via EventPattern (emit()); queries use MessagePattern (send()) with firstValueFrom.

Database: MongoDB (Typegoose ODM) for all NestJS services. PostgreSQL (SQLx) for Rust services (auth, uchat, SCIM).


2. Core User Flows (E2E)

Flow A: Visitor Browses โ†’ Buys โ†’ Tracks

Browser โ†’ Gateway โ†’ search (product discovery)
  โ†“
Browser โ†’ Gateway โ†’ products (product detail)
  โ†“
Browser โ†’ Gateway โ†’ ucart (addToCart, checkout)
  โ†“
ucart โ†’ payments (charge via Stripe)
  โ†“
payments โ†’ murchases (create Murchase record)
  โ†“
murchases โ†’ alerts (order confirmation email)
  โ†“
Browser โ†’ Gateway โ†’ murchases (trackMurchase)

Flow B: Owner Creates Malet โ†’ Lists Product โ†’ Fulfills Order

Browser โ†’ Gateway โ†’ auth (sign in)
  โ†“
Browser โ†’ Gateway โ†’ malets (createMalet with vertical config)
  โ†“
Browser โ†’ Gateway โ†’ products (createOneProduct)
  โ†“
[Visitor purchases โ€” see Flow A]
  โ†“
Browser โ†’ Gateway โ†’ murchases (advanceWorkroom)
  โ†“
murchases โ†’ alerts (shipping notification)

Flow C: Organization Lifecycle

Browser โ†’ Gateway โ†’ organizations (createOrganization)
  โ†“
organizations โ†’ payments (bootstrap_org_subscription โ†’ free Starter)
organizations โ†’ alerts (org_created notification)
  โ†“
Browser โ†’ Gateway โ†’ organizations (sendInvitation)
  โ†“
organizations โ†’ alerts (invitation email)
  โ†“
Browser โ†’ Gateway โ†’ malets (transferMaletToOrganization)
  โ†“
Browser โ†’ Gateway โ†’ organizations (deleteOrganization)
  โ†“ [BLOCKED if: active paid subscription OR owned Malets > 0]
organizations โ†’ alerts (organization_deleted notification)

3. Known Gaps & Workarounds

WARNING

These are known limitations that beta testers may encounter.

โœ… Fully Wired

Feature Notes
Guest checkout Email-only checkout, OTP lookup, order reassignment on account creation
Stripe payments Test mode; PaymentIntents for products, SetupIntents for subscriptions
Email notifications Via Resend (alerts service) โ€” purchase confirmations, OTP, org invites
WebSocket subscriptions Real-time notifications through Hive Gateway federation
Search sync Meilisearch with facets, real-time index sync via TCP events
Org subscription bootstrap Free Starter auto-created on org creation via TCP event
Org deletion safety Blocks deletion if active paid subscription or owned Malets
Malet transfers Bidirectional Personal โ†” Organization via Deck UI

๐ŸŸก Partially Wired (Mock/Stub)

Feature Current State Bug
Invoice history Billing page shows "Demo Data" badge with mock invoices P2 โ€” Stripe Customer ID not linked
Payment methods Mock card display on billing page P2 โ€” Stripe PaymentMethod API not exposed
Checkout totals Subscription checkout sidebar may show wrong amount Bug #71
Org invite in-app Email sent but no IN_APP AlertLog created Bug #72
Malet contact form UI exists, form submit is a no-op Bug #74
Onboarding flow Auth returns is_new_user but frontend doesn't redirect Bug #68

๐Ÿ”ด Not Built

Feature Notes
CI/CD pipeline Manual deploys only
Production domain No beta.mallnline.com DNS/SSL
Database backups No mongodump / pg_dump schedule
Error tracking No Sentry โ€” crashes invisible
M-Pesa payments Stripe is the only active processor

4. Event Flow Map

The platform uses NestJS TCP microservice transport for inter-service communication:

  • emit() โ€” Fire-and-forget (no response). Used for notifications and index updates.
  • send() โ€” Request-response (RPC). Used for queries like get_active_tier.

Event Flow Diagram

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    bootstrap_org_subscription     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚organizationsโ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚  payments   โ”‚
โ”‚            โ”‚    org_invite_created             โ”‚            โ”‚
โ”‚            โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   alerts    โ”‚
โ”‚            โ”‚    organization_deleted           โ”‚            โ”‚
โ”‚            โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   alerts    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    item_upserted / item_deleted   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  products   โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   search    โ”‚
โ”‚  services   โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚            โ”‚
โ”‚   blogs     โ”‚    blog_post_upserted            โ”‚            โ”‚
โ”‚   malets    โ”‚    malet_upserted/soft_deleted    โ”‚            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    order_status_changed           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  murchases  โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   alerts    โ”‚
โ”‚            โ”‚    workroom_action_required       โ”‚            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    issue_created/assigned          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  community  โ”‚    discussion_created/assigned    โ”‚   alerts    โ”‚
โ”‚            โ”‚    question_answered/flagged      โ”‚            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    user_created                   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚    auth     โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   nodes     โ”‚
โ”‚            โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   alerts    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Complete Event Registry

Verified from @EventPattern and .emit() calls across all subgraphs (2026-04-25).

Organization Lifecycle

Event Producer Consumer Pattern
bootstrap_org_subscription organizations payments emit
org_invite_created organizations alerts (email) emit
org_invite_sms organizations alerts (SMS) emit
organization_deleted organizations alerts emit
get_active_tier organizations, malets payments send (RPC)

Auth & Identity

Event Producer Consumer Pattern
user_created auth nodes, alerts emit
notify_email gateway, various alerts emit
send_sms / notify_sms various alerts emit

Commerce & Fulfillment

Event Producer Consumer Pattern
order_status_changed murchases alerts emit
workroom_action_required murchases alerts emit
payment_captured payments services (bookings) emit

Search Index Sync

Event Producer Consumer Pattern
item_upserted products, services search emit
item_deleted / item_soft_deleted products, services search emit
malet_upserted malets search emit
malet_soft_deleted / malet_restored malets search emit
malet_verification_updated malets search emit
malet_tags_updated malets search emit
blog_post_upserted / blog_post_deleted blogs search emit
rating_updated community search emit

Community & Alerts

Event Producer Consumer Pattern
issue_created / issue_assigned / issue_unassigned community alerts emit
issue_state_changed community alerts emit
discussion_created / discussion_assigned community alerts emit
question_answered / question_flagged community alerts emit
vertical_intelligence_suggestion malets alerts emit

Media

Event Producer Consumer Pattern
transcode_video_hls media video emit

5. "What Happens Whenโ€ฆ?" FAQ

Answers to lifecycle questions that beta testers and developers frequently ask.

What happens when I delete my Organization?

Pre-conditions (must all pass):

  1. โœ… No active paid subscription (Starter/free is OK)
  2. โœ… No owned Malets (transfer or delete them first)
  3. โœ… Actor has OWNER role

Cascade:

  • All memberships deleted
  • All pending invitations deleted
  • Organization record deleted
  • Audit event created (ORG_DELETED)
  • organization_deleted event emitted to alerts

What is NOT deleted: User accounts, personal Malets, payment history

What happens to org-owned Malets after org deletion?

With the new safety guards: You cannot delete an org that owns Malets. The deleteOrganization mutation returns:

"Cannot delete organization that owns 3 Malet(s). Transfer or delete all Malets before deleting the organization."

Use the Deck โ†’ Transfer button to move Malets back to your personal account first.

What happens when a subscription is cancelled?

  • Subscription status โ†’ CANCELLED at end of billing period
  • Org reverts to Starter plan limits (1 Malet, 3 members)
  • Excess Malets become read-only (not deleted)
  • Team members above the limit lose write access (not removed)
  • Data is never deleted โ€” renewing restores full access

What happens when a Malet is soft-deleted?

  • Malet status โ†’ TRASHED, hidden from all public surfaces
  • Products and services become invisible in search
  • Owner can restore from /trash within 30 days
  • After 30 days: permanently deleted (data + media purged)

What happens when a user deletes their account?

  • User record โ†’ soft-deleted, anonymized after 30-day grace period
  • Personal Malets โ†’ soft-deleted (same 30-day window)
  • Org memberships โ†’ removed (other members unaffected)
  • uChat messages โ†’ retained but author shown as "Deleted User"
  • Reviews/Q&A โ†’ retained but author anonymized

What happens when a product goes out of stock?

  • inventory.quantity โ†’ 0
  • Product still visible in storefront with "Out of Stock" badge
  • Add to uCart is disabled
  • Low stock alert fires if quantity < lowStockThreshold

6. Pre-Launch Checklist

Must-Have (Blocking)

  • All 17 subgraphs healthy and registered in gateway
  • Stripe test mode configured with webhook endpoint
  • Email delivery verified (Resend)
  • Placeholder content removed (press section, fake metrics)
  • Org deletion safety guards in place
  • FAQ page live at /help/faq with 25 categorized questions
  • Error boundaries on 17 routes
  • Workroom tracking UI for order fulfillment
  • Legal pages have "Draft โ€” Not Legally Reviewed" banner

Should-Have (Important)

  • Database backup strategy (MongoDB Atlas + cron)
  • CORS locked to production origins
  • Error monitoring (Sentry or equivalent)
  • Guest checkout smoke test (no account)
  • Multi-Malet uCart test (items from 2+ Malets)
  • Fix /help broken sub-routes
  • Fix /careers non-functional apply buttons
  • Empty state messages audit (lobby, uCart, murchases, notifications)
  • Loading skeleton audit (all data-fetching pages)
  • Mobile responsive audit (Safari + Chrome)

Nice-to-Have (Post-Beta)

  • Custom domain support
  • M-Pesa payment integration
  • Mobile app (KMP scaffold exists, iOS/Android shells not started)
  • AI-powered search recommendations (Intelligence service)

File Reference

Document Path Purpose
Backend TODO BACKEND_TODO.md Active backend tasks
Frontend TODO FRONTEND_TODO.md Active frontend tasks
Bug Tracker bugs.md All bugs with resolution status
Beta Audit beta-readiness-audit.md Original gap analysis (2026-04-24)
Org Lifecycle FAQ org-lifecycle-faq.md End-user FAQ about org lifecycle