Domain · Specifications

Freya Domain - Technical Specifications

Twenty-six packages, all published under the @freya/* scope at version

10sections37 minread

On this page

Luxury Goods and Fashion Intelligence. Implemented workspace domain — 26 capability/foundation libraries under libs/freya/*, the @freya/contracts package under libs/contracts/freya, and five applications under apps/freya/*. TODO Phase 57.

This specification documents what is implemented in code. Every schema, enum, state machine, endpoint, and event below is grounded in a named source file in the Freya workspace. Where a capability is described in features.md or TODOS/phase-57.md but not yet built, it is marked (planned).

The specification is organized to follow a reader top-down: package topology first, then the foundation layer (@freya/core types and @freya/db persistence), then the API surface, then the capability libraries, then the applications, configuration, requirements, and domain boundaries.

Package Topology#

Libraries (libs/freya/*)#

Twenty-six packages, all published under the @freya/* scope at version 0.1.0. Two are foundation packages; the rest are capability libraries owning one business unit each.

Package Directory Role
@freya/core libs/freya/core Foundation: shared domain types and utilities
@freya/db libs/freya/db Foundation: Drizzle schema, Redis/S3 config, observability
@freya/fashion libs/freya/fashion Apparel design pipeline
@freya/textiles libs/freya/textiles Dyeing, printing, finishing, vertical integration
@freya/beauty libs/freya/beauty Skincare, cosmetics, fragrance, haircare formulation
@freya/brand libs/freya/brand Brand architecture, positioning, storytelling, digital presence
@freya/ecommerce libs/freya/ecommerce Catalog, cart, checkout, payments, diaspora DTC
@freya/manufacturing libs/freya/manufacturing Batch, assembly, cosmetics, textile manufacturing
@freya/retail libs/freya/retail Store operations, clienteling, customer experience
@freya/academy libs/freya/academy Curriculum, students, certification
@freya/jewelry libs/freya/jewelry Ethical gold jewelry, production, craft preservation
@freya/market-intel libs/freya/market-intel Trend monitoring, competitive intelligence, market research
@freya/financials libs/freya/financials Unit economics, financial planning, startup investment
@freya/connectors libs/freya/connectors Cross-domain integration (Asase, Brigid, Cybele, Saraswati, Maat)
@freya/sota libs/freya/sota AI design, analytics, computer vision, NLP, blockchain auth, virtual try-on
@freya/watches libs/freya/watches Watch line management
@freya/perfumes libs/freya/perfumes Fragrance bench, accord design, maceration tracking
@freya/bridal-events libs/freya/bridal-events Bridal couture and event wardrobe
@freya/hair-care libs/freya/hair-care Afro-textured hair-care formulation
@freya/home-decor libs/freya/home-decor Interior textiles and home decor
@freya/footwear libs/freya/footwear Footwear design and production
@freya/eyewear libs/freya/eyewear Optical and sun eyewear
@freya/luggage-leather libs/freya/luggage-leather Luggage and leather goods
@freya/personal-care libs/freya/personal-care Personal-care formulation
@freya/cleaning-products libs/freya/cleaning-products Detergent and cleaning products
@freya/textile-finishing libs/freya/textile-finishing Dye-house, print-house, finishing-line operations

@freya/contracts (libs/contracts/freya, version 0.1.0) is a separate contracts package holding the Zod request/response schemas shared across the API and consuming services.

Applications (apps/freya/*)#

Five applications, all published at version 0.0.1. Their package.json names collide with library names by design (the apps are not consumed as libraries).

Package name Directory Purpose
@freya/api apps/freya/api REST + GraphQL + gRPC + WebSocket API surface, OpenAPI spec, event bus
@freya/studio apps/freya/studio Design and brand studio: trend boards, collection dashboard, tech-pack editor
@freya/shop apps/freya/shop Direct-to-consumer storefront: listing, detail, cart, checkout, subscription box
@freya/retail apps/freya/retail Retail-operations app: store dashboard, clienteling, inventory lookup, staff
@freya/manufacturing apps/freya/manufacturing Factory-floor app: order management, batch records, quality inspection, waste reporting

Foundation: @freya/core#

@freya/core (libs/freya/core/src/index.ts) is the type and utility foundation every capability library imports. Its source modules are product-types.ts, material-types.ts, supply-chain-types.ts, brand-customer-types.ts, beauty-types.ts, business-units.ts, and utilities.ts.

Branded ID Types#

From product-types.ts, six template-literal branded ID types prevent cross-entity reference confusion at compile time. Each carries a fixed prefix that makes IDs self-documenting and ensures the TypeScript compiler rejects a FreyaOrderId where a FreyaProductId is expected.

Type Prefix Identifies
FreyaProductId FPRD- Product
FreyaCollectionId FCOL- Collection
FreyaOrderId FORD- Customer order
FreyaCustomerId FCUS- Customer
FreyaVariantId FVAR- Product variant
FreyaSkuId FSKU- SKU

The ID generators (generateProductId, generateCollectionId, generateOrderId, generateCustomerId, generateVariantId) build IDs as PREFIX{hexTimestamp}-{6-hex-sequence}-{4-hex-random}. The monotonic sequence wraps at 0x1000000.

Product-Domain Enums (product-types.ts)#

These enums define the shared vocabulary for product lifecycle, markets, currencies, seasons, and categories. All capability libraries and the API use these same values.

  • ProductStatus — the product lifecycle: Concept, InDevelopment, Sampling, PreProduction, InProduction, ReadyToShip, Active, Discontinued.
  • FashionSeasonSS (Spring/Summer), FW (Fall/Winter), Resort, PreFall, Capsule, Perennial.
  • FreyaCurrencyGHS, NGN, USD, GBP, EUR, CAD, ZAR.
  • MarketRegionGhana, Nigeria, UK, USA, Canada, Germany, Netherlands, Pan_Africa.
  • ProductCategory — nineteen values: fashion_rtw, fashion_couture, watches, textiles_fabric, textiles_finished, skincare, cosmetics, perfume, hair_care, personal_care, detergent, bridal, jewelry, footwear, eyewear, luggage, interior_textiles, accessories, educational.

Product Entity#

Product (product-types.ts) is the central entity. The table below documents every field and its meaning.

Field Type Required Meaning
productId FreyaProductId yes Branded product identity
name string yes Display name
description string yes Long description
category ProductCategory yes Product category
buCode string yes Owning business-unit code
brand string yes Brand identity
status ProductStatus yes Lifecycle status
variants ReadonlyArray<ProductVariant> yes Sellable variants
pricingTiers ReadonlyArray<PricingTier> yes Multi-tier pricing
targetMarkets ReadonlyArray<MarketRegion> yes Intended markets
certifications ReadonlyArray<string> yes Held certifications
sustainabilityScore number yes Sustainability score
createdAt / updatedAt string yes ISO timestamps

ProductVariant carries per-SKU details: variantId (FreyaVariantId), sku (FreyaSkuId), optional barcode, optional size/color/material, stockByLocation (Record<string, number> — quantity keyed by location), costGhs, optional weight, and optional dimensions ({ length, width, height }).

PricingTier models multi-tier, multi-currency pricing: tierId, tierName (one of retail, wholesale, vip, diaspora_premium, trade), prices (a MultiCurrencyPrice map of currency-code → amount), minimumOrderQuantity, discountPct.

getPriceForMarket(product, market, tier, currency) resolves a price by looking up the named tier, preferring the requested currency, and falling back to the market's default currency via a fixed market→currency map (GhanaGHS, NigeriaNGN, UKGBP, USAUSD, CanadaCAD, Germany/NetherlandsEUR, Pan_AfricaGHS).

Collection Entity#

Collection (product-types.ts) groups related products for a season. It carries: collectionId (FreyaCollectionId), name, brand, season (FashionSeason), year, theme, optional culturalInspiration, productIds (array of FreyaProductId), launchDate, targetMarkets, priceRangeGhs ({ min, max }), numberOfLooks, designerName, and a status of concept, design, production, launched, or archived.

LimitedEdition tracks numbered drops: productId, editionName, totalUnits, remainingUnits, authenticationCode (8-hex), numbering, premiumPct, launchAt, optional expiresAt. buildLimitedEdition constructs it with remainingUnits equal to totalUnits and numbering of 1/{totalUnits}.

Material and Textile Types (material-types.ts)#

These enums and types model the physical materials that go into a luxury product. They cover textiles, leathers, metals, gemstones, chemicals, and botanical ingredients.

Enums:

  • FiberTypecotton, silk, wool, polyester, viscose, bamboo, hemp, kente_silk, ashanti_cotton, linen, nylon, acrylic, lurex.
  • TextileFinishwax_print, batik, tie_dye, digital_print, screen_print, embroidery, beading, smocking, applique, plain.
  • AfricanPrintTypeAnkara, Kente, Adinkra, Bogolan, Shweshwe, Aso_Oke, Kuba, Brocade.
  • LeatherTypefull_grain, top_grain, genuine, bonded, vegan_pu, vegan_cork, suede.
  • MaterialGradeScoreA+, A, B, C, Reject.

Material is the core material record: materialId, name, type (textile, leather, metal, gemstone, chemical, botanical, packaging), gradeScore (MaterialGradeScore), supplierId, pricePerUnitGhs, unit (metre, kg, litre, piece, carat), minimumOrderUnits, leadTimeDays, certifications, sustainabilityScore.

Textile extends material for woven and knitted fabrics: textileId, name, composition (array of FiberComposition), weaveType (plain, twill, satin, jacquard, knit, nonwoven, lace), weightGSM, widthCm, optional countOrDenier, origin, certifications, sustainabilityRating, priceGhsPerMeter.

FiberComposition records a single fiber's contribution: fiberType, percentagePct. Colorway models the precise color specification for a dye lot: colorwayId, name, pantoneCode, hexCode, rgbValues, dyeFormula, colorToleranceDeltaE, and four colorfastness ratings (fastnessCrockWet, fastnessCrockDry, fastnessWash, fastnessLight).

AfricanPrint captures culturally significant textile patterns: printId, printType, name, culturalOrigin, culturalSignificance, colorways, repeatPatternCm, minimumOrderMeters, leadTimeDays, optional artisanCoopName, geoprotectionApplied.

TextileTest records a fabric quality test against a laboratory standard: testId, textileId, testType (tensile_strength, colorfastness, shrinkage, pilling, abrasion, bursting_strength), standard, result, unit, passFailThreshold, passed, testedAt, labName.

Three algorithmic invariants are enforced in code. validateFiberComposition requires fiber percentages to sum to 100% within ±0.5. classifyTextileWeight buckets GSM as ultra_light (<100), light (<200), medium (<350), heavy (≤500), extra_heavy (>500). computeDeltaE is a simplified CIE76-style RGB color difference calculation used to evaluate colorway matching.

Supply-Chain and Manufacturing Types (supply-chain-types.ts)#

These types model the supplier tier structure, manufacturing order lifecycle, AQL quality inspection logic, and shipment tracking.

Enums:

  • SupplierTiertier_1, tier_2, tier_3.
  • SupplierCertificationISO9001, OEKO_TEX, GOTS, Fairtrade, SEDEX, SA8000, WRAP, FSC.
  • OrderStatus (supply-chain order) — draft, placed, confirmed, in_production, quality_check, ready, shipped, delivered, cancelled.
  • InspectionResultpass, conditional_pass, fail, pending.

Supplier records everything Freya needs to evaluate and manage a supply relationship: supplierId, name, country, city, tier, capabilities, certifications (array of SupplierCertification), leadTimeDays, minimumOrderValue, currency, performanceScore, onTimeDeliveryPct, qualityPassRatePct, contactEmail, optional activeContractEnd.

Artisan tracks individual craft practitioners: artisanId, name, craft, communityName, region, skillLevel (apprentice, journeyman, master, grandmaster), yearsExperience, dailyCapacityUnits, rateGhsPerDay, portfolioUrls, fairtradeRegistered.

BOMLine captures one line of a bill of materials: materialId, materialName, quantityPerUnit, unit, wastageAllowancePct, totalQuantityRequired, unitCostGhs, totalCostGhs.

ManufacturingOrder (core type) is the production instruction for one product variant: orderId, productId (FreyaProductId), variantId (FreyaVariantId), quantity, supplierId, bom (array of BOMLine), totalBOMCostGhs, manufacturingCostGhs, totalCostGhs, targetStartDate, targetCompletionDate, status (OrderStatus), qualityInspections (array of inspection IDs), lotNumber.

QualityInspection records AQL sampling evidence for a batch: inspectionId, orderId, productId, inspectionType (incoming, in_process, final, shipment), inspectedUnits, acceptableQualityLevel, defectsFound (array of { category, severity: critical|major|minor, count }), result (InspectionResult), inspectorId, inspectedAt, notes.

ShipmentTracking records a physical shipment's movement through customs and delivery: shipmentId, orderId, carrier, trackingNumber, origin, destination, optional departedAt, estimatedArrivalAt, optional actualArrivalAt, customsStatus (not_required, filed, under_review, cleared, held), status (pending, in_transit, at_customs, delivered, exception), insuranceValueGhs.

Three AQL quality functions are implemented. computeAQLSampleSize returns standard sample sizes per lot size (lot <50→5, ≤90→8, ≤150→13, ≤280→20, ≤500→32, ≤1200→50, else 80). evaluateQualityResult returns fail on any critical defect or majors exceeding the AQL threshold, conditional_pass on minors exceeding twice that threshold, and pass otherwise. computeSupplierScore is a weighted aggregate: performanceScore × 0.4 + onTimeDeliveryPct × 0.3 + qualityPassRatePct × 0.3.

Brand and Customer Types (brand-customer-types.ts)#

These types model brand positioning hierarchies and customer segmentation, which together drive pricing, campaign targeting, and loyalty management.

Enums:

  • CustomerSegmentfashionista, conscious_consumer, heritage_seeker, luxury_buyer, diaspora_elite, mass_market.
  • LoyaltyTierbronze, silver, gold, platinum, obsidian.

Brand models a brand's identity and market position: brandId, name, optional parentBrand, positioning (ultra_luxury, luxury, premium, accessible_premium, mass), targetSegments, heritageStory, foundingYear, foundingCountry, designerName, optional logoUrl, brandColors, brandFonts, optional instagramFollowers, sustainabilityCommitments.

Customer carries the full profile needed for personalization and loyalty: customerId (FreyaCustomerId), firstName, lastName, email, optional phoneNumber, country, city, segment, loyaltyTier, loyaltyPoints, lifeTimeValueGhs, preferredCurrency, preferredCategories, sizes (Record<string, string>), optional skinTone/hairType, purchaseCount, optional lastPurchaseAt, registeredAt.

DiasporaMarket, LoyaltyProgram, and InfluencerPartnership are also defined here. classifyCustomerSegment derives a segment algorithmically from lifetime value, purchase count, and category affinity, using the following rules: luxury affinity + LTV ≥ 50000 → luxury_buyer; LTV ≥ 20000 with ≥10 purchases → diaspora_elite; heritage affinity with ≥3 purchases → heritage_seeker; beauty affinity with ≥5 purchases → fashionista; LTV ≥ 5000 with ≥5 purchases → conscious_consumer; otherwise mass_market.

Beauty and Formulation Types (beauty-types.ts)#

These types model the scientific and regulatory dimension of beauty product development, covering ingredient chemistry, stability testing, and regulatory submission.

Enums:

  • FragranceFamilyfloral, oriental, woody, fresh, fougere, chypre, gourmand, aquatic.
  • HairType — the twelve Andre Walker classes 1A4C.
  • SkinTypenormal, dry, oily, combination, sensitive, mature.
  • FitzpatrickScale — numeric 16.
  • FormulationStatusconcept, development, stability_testing, approved, production, discontinued.

INCIIngredient records a single ingredient per the INCI naming convention: inciName, commonName, percentagePct, function (array of strings), origin (natural, synthetic, nature_identical, biotechnology), supplierId, safetyAssessmentRef, isActiveIngredient, optional regulatoryRestriction.

Formulation is the versioned formulation record for a beauty product: formulationId, name, category (skincare, cosmetics, hair_care, fragrance, personal_care, detergent), ingredients (array of INCIIngredient), phRange ({ min, max }), optional viscosityCps, appearanceDescription, shelfLifeMonths, storageConditions, status (FormulationStatus), version, createdAt, optional regulatoryRef.

FragranceNote records one ingredient's role in a fragrance accord: ingredientId, inciName, noteType (top, heart, base), family, odorIntensity, longevityHours, percentageInAccord.

StabilityTest records a time-point stability test result: testId, formulationId, protocol (ICH_Q1A, accelerated_40C, cycling, photo_stability), timePointWeeks, conditions, parameters (record of { value, specification, passed }), overallResult (pass, fail, pending), testedAt.

RegulatorySubmission tracks market-specific regulatory filing: submissionId, formulationId, market, regulatoryBody (Ghana_FDA, EU_SCCS, US_FDA, NAFDAC), submissionType (registration, notification, cpsr, renewal), status (draft, submitted, under_review, approved, rejected), optional submittedAt, approvedAt, expiryAt, registrationNumber.

Three algorithmic functions are provided. validateINCISum enforces ingredient percentages summing to 100% ±0.5. computeFragranceAccordStrength weights base notes ×1.5, heart ×1.2, top ×1.0. getHairTypeRecommendations and getSkinTypeIngredients return domain-specific product/ingredient guidance per hair type and skin type.

Business-Unit Catalog (business-units.ts)#

FreyaBusinessUnitCode enumerates the nineteen business units that Freya manages: fashion, watches, textiles, beauty, perfumes, bridal-events, ecommerce, manufacturing, hair-care, home-decor, jewelry, footwear, eyewear, academy, luggage-leather, personal-care, retail, cleaning-products, textile-finishing.

FREYA_BUSINESS_UNIT_CATALOG is a frozen array of nineteen FreyaBusinessUnitProfile records. Each profile carries code, packageName (@freya/...), displayName, summary, primaryCategories, operatingCapabilities, productionModels, commercialChannels, and keyMetrics. The assertion assertCompleteFreyaBusinessUnitCatalog enforces exactly nineteen entries with unique codes and packages, protecting the catalog against accidental omission.

Core Utilities (utilities.ts)#

utilities.ts provides deterministic helpers used across the capability libraries so each library does not implement its own version of common calculations.

  • SKU generationgenerateSKU(buCode, category, year, sequence) builds FSKU-{BU}-{CAT}-{YY}-{SSSS} using a fixed category→3-letter abbreviation map (fashion_rtwRTW, jewelryJWL, etc.).
  • BarcodesgenerateEAN13/validateEAN13Checksum and generateUPCA/validateUPCAChecksum implement the standard EAN-13 and UPC-A check-digit algorithms.
  • CurrencyEXCHANGE_RATES_TO_GHS holds fixed GHS conversion rates for every FreyaCurrency; convertToGHS, convertFromGHS, and formatCurrency (with per-currency symbols) operate on it.
  • Textile conversionsyardsToMeters, metersToYards, gsmToOzPerSqYard, denierToTex, threadCountToGSM.
  • Pantone matchingGHANA_FASHION_PALETTE is a twelve-color Kente/Ankara palette; findNearestPantone returns the closest palette color by simplified Delta-E distance.
  • Error typesFreyaError (base class, with code and optional buCode), FreyaValidationError (FREYA_VALIDATION_ERROR), FreyaNotFoundError (FREYA_NOT_FOUND), FreyaBusinessRuleError (FREYA_BUSINESS_RULE_VIOLATION).

Persistence: @freya/db#

@freya/db (libs/freya/db/src) owns all persistence infrastructure for the Freya domain. Source modules: schema.ts, connection.ts, redis-config.ts, s3-config.ts, observability.ts, seed.ts. Capability libraries import from this package to get schema types; they never construct their own database connections.

PostgreSQL Schema (schema.ts)#

All tables and enums are prefixed freya_. The Drizzle migration filter is tablesFilter: ['freya_*'] (connection.ts). Tables use UUID primary keys (uuid('id').defaultRandom()), timezone-aware created_at/updated_at timestamps, and jsonb columns for nested structures. The pgvector extension provides vector(1536) embedding columns for catalog, collection, recommendation, and trend-clustering similarity search.

Schema Enums#

schema.ts declares the following Postgres enums. Note that the Drizzle enum value sets differ from the @freya/core string-union sets by design: @freya/core types model in-process domain logic with PascalCase values; schema.ts enums model persisted Postgres columns with snake_case values. The two are not kept textually identical.

  • freya_product_statusconcept, in_development, sampling, pre_production, in_production, ready_to_ship, active, discontinued.
  • freya_business_unitfashion, textiles, beauty, skincare, haircare, fragrance, jewelry, footwear, eyewear, home_decor, luggage, personal_care, detergent, academy, retail, ecommerce, bridal, watches (eighteen values).
  • freya_product_category — sixty-two values grouped by domain: fashion (dress, top, trouser, skirt, jacket, coat, suit, jumpsuit, swimwear, sportswear); accessories (bag, wallet, belt, hat, scarf, gloves, sunglasses, watch); shoes (heels, flats, sandals, boots, sneakers, loafers, oxfords); beauty (foundation, lipstick, eyeshadow, mascara, blush, serum, moisturizer, cleanser, toner, sunscreen); haircare (shampoo, conditioner, treatment, styling, tools, extensions); fragrance (eau_de_parfum, eau_de_toilette, body_mist, candle, diffuser); jewelry (necklace, ring, earring, bracelet, anklet, brooch, cufflinks); home (bedding, curtains, cushion, throw, rug, lampshade); personal care (soap, lotion, deodorant, sanitizer, dental, shaving); detergent (laundry_powder, laundry_liquid, fabric_softener, dishwashing, floor_cleaner).
  • freya_seasonSS, FW, Resort, PreFall, Capsule, Bridal, Couture.
  • freya_collection_typeseasonal, capsule, collaboration, limited_edition, bridal, couture.
  • freya_material_typetextile, leather, metal, gemstone, botanical, chemical, synthetic.
  • freya_fiber_typecotton, silk, wool, polyester, viscose, bamboo, hemp, linen, kente_silk, local_cotton, cashmere, mohair, lyocell, nylon, acrylic.
  • freya_textile_finishwax_print, batik, tie_dye, digital_print, screen_print, embroidery, beading, smocking, applique, laser_cut, pleating, quilting, burnout.
  • freya_order_statuspending, confirmed, processing, shipped, delivered, cancelled, refunded, return_requested, returned.
  • freya_manufacturing_statusplanned, in_progress, quality_check, completed, on_hold, cancelled.
  • freya_quality_resultpassed, failed, conditional_pass, pending_retest.
  • freya_customer_segmentvip, premium, regular, new, diaspora, wholesale, corporate.
  • freya_loyalty_tierbronze, silver, gold, platinum, diamond.
  • freya_currencyGHS, NGN, USD, GBP, EUR, CAD, ZAR, KES.
  • freya_marketghana, nigeria, kenya, south_africa, uk_diaspora, us_diaspora, canada_diaspora, eu_diaspora.
  • freya_store_typeflagship, pop_up, duty_free, mall_kiosk, market_stall, studio, warehouse, outlet.
  • freya_inspection_typefabric, garment, cosmetics, jewelry, packaging, finished, raw_materials, in_process.
  • freya_certification_statuspending, approved, rejected, expired, under_review.
  • freya_asset_typelogo, sketch, tech_pack, pattern, cad, mood_board, product_photo, lifestyle_photo, video, ar_model.
  • freya_trend_sourceinstagram, tiktok, pinterest, runway, street_style, celebrity, editorial, trade_show, sales_data, search.
  • freya_academic_statusenrolled, active, on_leave, graduated, withdrawn, suspended.

Schema Tables#

Twenty-four tables form the persistent core of the domain, exported as the schema object. Every table uses UUID primary keys and targeted B-tree indexes; unique indexes enforce the business keys listed at the end of this section.

  • freya_products — catalog row. Key columns: sku (unique index), ean13, upc_a, name, business_unit, category, status (default concept), brand_idfreya_brands, collection_idfreya_collections, base_price_amount/base_price_currency, market_prices (jsonb), weight_kg, dimensions_cm, materials (jsonb array of { materialId, pct }), country_of_origin, sustainability_rating, certifications, embedding (vector(1536)), ai_tags, is_limited_edition, edition_size, edition_number, launch_date, discontinue_date, metadata. Indexed on sku, business_unit, status, brand_id, collection_id.
  • freya_product_variantsproduct_idfreya_products (cascade delete), sku_suffix, full_sku (unique), size, color_name, color_pantone, color_hex, material_variant, weight_kg, price_adjustment, inventory_quantity, reserved_quantity, reorder_point, reorder_quantity, warehouse_location, barcode, is_active, image_urls.
  • freya_collectionsname, slug (unique), type, season, year, brand_id, theme, mood_board_urls, color_palette, style_count_target, launch_date, markets, price_range_min/price_range_max/currency, is_numbered, total_pieces, collaborator_name, collaborator_type, embedding (vector(1536)). Indexed on slug, (season, year), type, brand_id.
  • freya_materialscode (unique), name, type, textile columns (fiber_composition, weave_type, weight_gsm, width_cm, thread_count, finish), leather columns (leather_type, tannage, thickness_mm), metal/gemstone columns (purity, carat, cut, clarity, color_grade), beauty-ingredient columns (inci_name, cas_number, ph_range_min/ph_range_max, max_use_pct, eu_restricted), quality and sustainability (grade, sustainability_score, certifications, origin_country, origin_region), supplier linkage (supplier_idfreya_suppliers, unit_of_measure, unit_cost, cost_currency, lead_time_days, minimum_order_quantity), storage (storage_conditions, shelf_life_months), and African-textile cultural metadata (cultural_origin, cultural_significance, pattern_name, is_heritage).
  • freya_supplierscode (unique), name, type, location columns, contact columns, capability columns (business_units, product_categories, capabilities, MOQ fields), performance ratings (quality_rating/delivery_rating/communication_rating/overall_rating, on_time_delivery_pct, defect_rate_pct, average_lead_time_days), certifications (jsonb array of { name, body, expiry, verified }), is_verified, is_active, payment_terms_days, preferred_currency.
  • freya_artisanscode (unique), name, craft_type, location columns, years_experience, specializations, certifications, portfolio_urls, capacity columns (monthly_capacity_units, typical_lead_time_days, day_rate_amount/day_rate_currency), cooperative columns, is_certified_fair_trade, ratings, bio, heritage_story.
  • freya_manufacturing_ordersorder_number (unique), type, business_unit, status (default planned), priority, product linkage (product_id, variant_id, collection_id), production columns (facility_id, supplier_id, artisan_id, quantity, batch_size, quantity_completed, quantity_rejected, yield_pct), bom (jsonb), scheduling timestamps (planned_start_date, actual_start_date, target_completion_date, actual_completion_date), cost columns, labor_hours, quality_standard, quality_result, and routing (jsonb array of { step, operation, workstation, durationMin, completedAt? }).
  • freya_customersemail (unique), name/phone columns, date_of_birth, gender, market, segment (default new), loyalty_tier (default bronze), loyalty_points, lifetime_points, diaspora columns (is_diaspora, origin_country, diaspora_country), financial columns (total_spend_ghs, order_count, average_order_value_ghs, last_purchase_at), preference columns (preferred_language, preferred_currency, preferred_categories, preferred_sizes, preferred_colors, preferred_brands, preferred_price_range, preferred_communication), VIP columns, body-measurement columns (measurements, hair_type, skin_type, fitzpatrick_scale), preference_embedding (vector(1536)), and consent columns (marketing_consent, data_processing_consent, consents_updated_at).
  • freya_retail_locationscode (unique), name, type, brand_id, location/geo columns, lease columns, operations columns (opening_hours, staff_count, pos_terminal_count, manager contact), KPI columns (monthly_revenue_target_ghs, avg_daily_footfall, conversion_rate_pct, nps_score), business_units, and facility flags (has_fitting_room, has_vip_lounge, has_alteration_service, has_fragrance_bar).
  • freya_ordersorder_number (unique), customer_idfreya_customers, channel, market, status (default pending), lines (jsonb array of order-line objects), shipping_address/ billing_address (jsonb), pricing columns (subtotal, shipping_cost, discount_amount, tax_amount, total, currency), payment columns (payment_method, payment_reference, payment_status, paid_at), shipping columns (shipping_method_id, carrier, tracking_number, estimated_delivery, delivered_at), promotion columns (promo_code, loyalty_points_earned, loyalty_points_redeemed, gift_message, gift_wrap), and retail_location_idfreya_retail_locations for click-and-collect.
  • freya_cartssession_id (unique), customer_id, market, currency, lines (jsonb), promo_code, discount_amount, total_items, subtotal, expires_at.
  • freya_wishlistscustomer_idfreya_customers (cascade), name, is_public, share_token, items (jsonb).
  • freya_virtual_tryon_sessionscustomer_id, session_token (unique), product_id, variant_id, input columns (body_photo_url ephemeral — deleted after the session to satisfy privacy requirements, measurements_used), output columns (result_image_url, result_video_url, fit_assessment, recommended_size), feedback columns (customer_rating, added_to_cart, purchased), technical columns (ar_engine, processing_time_ms), expires_at.
  • freya_brandscode (unique), name, parent_brand_id (self-referential), positioning columns (tier, tagline, heritage_story, founding_year, founded_in), identity columns (colors, fonts, logo_url, brand_book_url), target-market columns, social-media handles, and metrics (brand_equity_score, nps_score, social_followers).
  • freya_brand_campaignsbrand_idfreya_brands, name, type, channels, markets, date columns, budget columns, KPI columns (target/actual impressions, conversions, revenue, roas), content columns (creative_assets, hashtags, influencer_ids), status.
  • freya_influencer_partnershipsbrand_idfreya_brands, influencer columns, platform, handle, followers, engagement_rate_pct, niche, tier, market, contract columns, fee_per_post/fee_currency, deliverables (jsonb), performance (jsonb), status.
  • freya_quality_inspectionsinspection_number (unique), type, manufacturing_order_idfreya_manufacturing_orders, batch_id, product_id, supplier_id, inspector columns, AQL sampling columns (lot_size, sample_size, aql_level, aql_critical default 0, aql_major default 2.5, aql_minor default 4.0), result columns (samples_inspected, defects_found, critical_defects, major_defects, minor_defects, defect_rate_pct, defect_details, result), test_results (jsonb), gmp_checks (jsonb — cosmetics GMP), corrective_actions (jsonb), retest_required, retest_date, certificate_url.
  • freya_academy_studentsstudent_number (unique), email (unique), name/contact columns, status (default enrolled), enrollment/graduation dates, programme, specialization, cohort, scholarship_type, tuition_paid, gpa, portfolio_url, certifications_earned (jsonb), employment columns.
  • freya_academy_coursescode (unique), title, programme, level (100–400), credits, duration_weeks, description, learning_outcomes, prerequisites, instructor_id, materials_required, max_enrollment.
  • freya_academy_enrollmentsstudent_idfreya_academy_students (cascade), course_idfreya_academy_courses, academic_year, semester, grade, grade_letter, attendance_pct, status, completed_at.
  • freya_formulationscode+version (unique pair), name, business_unit, category, subcategory, product_type, ingredients (jsonb array of INCI ingredient objects), total_batch_size_kg, physical-chemical specs (ph_min/ph_max, viscosity, density_g_ml, color/odor/appearance specs), safety columns (preservative_system, spf_value, is_allergen_free, allergens_present, eu_compliant, ghana_fda_approved, nafdac_approved), stability columns (shelf_life_months, storage_conditions, stability_results), fragrance-note columns (fragrance_family, top_notes, middle_notes, base_notes), efficacy_claims (jsonb), cost_per_kg/cost_currency, status, is_approved, approved_by, approved_at.
  • freya_trend_signalssource, source_id, source_url, classification columns (business_unit, category, trend_name, tags), cultural columns (cultural_context, markets), metric columns (engagement_count, view_count, share_count, sentiment_score, virality_score, trend_velocity), AI-analysis columns (summary, design_recommendations, color_palette, material_suggestions), content_embedding (vector(1536)), lifecycle flags (is_emerging, is_mainstream, is_declining), peak_prediction_date, captured_at.
  • freya_financial_recordsperiod_year+period_month+business_unit +market (unique tuple), retail_location_id, revenue columns (gross_revenue_ghs, net_revenue_ghs, returns_amount_ghs, discount_amount_ghs), COGS columns (cogs_ghs, material_cost_ghs, labor_cost_ghs, overhead_cost_ghs), margin columns (gross_margin_ghs, gross_margin_pct), opex columns, EBITDA columns, volume columns (units_sold, transactions, average_transaction_value_ghs), inventory columns (inventory_value_ghs, inventory_turnover, days_inventory_outstanding), and accounts columns.
  • freya_inventory_valuationsvaluation_date, business_unit, product_idfreya_products, variant_id, quantity_on_hand, unit_cost_ghs, total_value_ghs, valuation_method (default FIFO), location_id.

Schema Indexes and Partitioning Notes#

Every table declares targeted B-tree indexes. Unique indexes enforce business keys: freya_products.sku, freya_product_variants.full_sku, freya_collections.slug, freya_materials.code, freya_suppliers.code, freya_artisans.code, freya_manufacturing_orders.order_number, freya_customers.email, freya_retail_locations.code, freya_orders.order_number, freya_carts.session_id, freya_virtual_tryon_sessions.session_token, freya_brands.code, freya_quality_inspections.inspection_number, freya_academy_students.student_number and email, freya_academy_courses.code, the (code, version) pair on freya_formulations, and the (period_year, period_month, business_unit, market) tuple on freya_financial_records. Query-pattern indexes cover status, business-unit, foreign-key, and time-range filters (for example freya_orders is indexed on customer_id, status, market, and created_at; freya_trend_signals on source, business_unit, virality_score, captured_at, and is_emerging). The five vector(1536) columns (freya_products.embedding, freya_collections.embedding, freya_customers.preference_embedding, freya_trend_signals.content_embedding) support pgvector similarity search for catalog, collection, recommendation, and trend-clustering queries.

Connection Pooling (connection.ts)#

buildFreyaDbPoolConfig(serviceRole, overrides) sizes the connection pool differently per service role, reflecting the read/write intensity of each service. It produces a FreyaDbPoolConfig as follows: ecommerce (max 10 with PgBouncer / 20 direct, min 2), manufacturing (5/10, min 1), analytics (3/5, min 1), admin (3/5, min 1), background (2/3, min 0). It reads FREYA_DATABASE_URL (falling back to DATABASE_URL, then postgresql://oshun:oshun_dev@localhost:5432/freya), sets a 30-second statement_timeout, and toggles PgBouncer transaction mode when FREYA_USE_PGBOUNCER is true. buildReadReplicaConfig routes analytics/reporting reads to weighted replicas listed in FREYA_DATABASE_REPLICA_URLS. buildPgBouncerUrl rewrites the port to PGBOUNCER_PORT (default 6432) and disables prepared statements. The Drizzle migration config (FREYA_DRIZZLE_CONFIG) points at schema.ts, outputs to libs/freya/db/drizzle, dialect postgresql, with tablesFilter: ['freya_*'].

Redis Caching (redis-config.ts)#

Redis is central to Freya's real-time commerce behavior: inventory availability, cart state, and pricing are all read from Redis rather than Postgres on the hot path.

FREYA_REDIS_PREFIX is freya. FreyaRedisKeys builds namespaced keys for inventory (freya:inv:{variantId}), product catalog, collection, customer session/profile/loyalty, cart, exchange rates, per-market product price, store KPIs and footfall, trend scores, API and checkout rate-limit counters, virtual-try-on session, and distributed locks (freya:lock:inv:{variantId}, freya:lock:checkout:{orderId}).

FreyaRedisTTL defines TTLs in seconds: inventory 30, product 600, product search 120, collection 3600, session 86400 (sliding), customer profile 900, cart 604800, exchange rates 900, product price 900, store KPI 300, trend score 3600, trending-now 1800, rate limit 60, lock 10, try-on session 1800. FreyaInvalidationPatterns defines SCAN-based bulk invalidation groups.

FreyaPubSubChannels defines the six Redis pub/sub channels used for low-latency fan-out to connected clients: freya:pubsub:inventory, freya:pubsub:order_status, freya:pubsub:price, freya:pubsub:store_kpi, freya:pubsub:trend, freya:pubsub:cart. buildInventoryCacheEntry computes a write-through InventoryCacheEntry whose available is max(0, inventoryQty - reservedQty). buildFreyaRedisConfig reads FREYA_REDIS_URL/REDIS_URL (default redis://localhost:6379).

Object Storage (s3-config.ts)#

Three MinIO/S3 buckets serve different asset types with different access and retention policies:

  • freya-design-assets — private, signed URLs only, versioned, with a 730-day Glacier transition for archived designs. Used for sketches, tech packs, patterns, mood boards, and CAD files.
  • freya-product-imagery — public CDN-served, not versioned, 365-day expiration. Used for studio shots, lifestyle images, 360-degree frames, and AR .glb models.
  • freya-manufacturing-docs — strictly private, versioned, retained for regulatory compliance. Used for GMP batch records, QC reports, QC photos, certificates, and formulation documents.

FreyaS3Keys defines object-key conventions per asset class. FREYA_S3_SIGNED_URL_TTL sets signed-URL lifetimes per class. buildFreyaS3Config reads FREYA_S3_ENDPOINT, FREYA_S3_REGION, FREYA_S3_ACCESS_KEY, FREYA_S3_SECRET_KEY, and FREYA_CDN_BASE_URL, and forces path-style addressing for MinIO.

Observability (observability.ts)#

FREYA_OTEL_CONFIG configures OpenTelemetry tracing. FREYA_PROMETHEUS_METRICS defines the Prometheus metric catalog and FREYA_METRICS_CONFIG its scrape settings. Structured logging uses FreyaLogEntry with LogLevel of debug, info, warn, error, fatal. FREYA_CIRCUIT_BREAKERS defines per-service circuit-breaker configs with a CircuitBreakerState of closed, open, or half_open; shouldOpenCircuit and shouldCloseCircuit implement the transition logic.

Reference Seed Data (seed.ts)#

seed.ts ships reference datasets used during development and testing rather than transactional rows. It includes: FABRIC_REFERENCE (African textile types with GSM ranges, fiber composition, cultural origin and significance, and isHeritage flags — e.g. Ankara wax print, Kente cloth), ingredient INCI references, GIA-standard gemstone grades, the African Pantone palette, and per-market standard size charts.

API Surface: apps/freya/api#

@freya/api (apps/freya/api/src) exposes the Freya domain through REST, GraphQL, gRPC, and WebSocket interfaces. Source modules: schemas.ts, middleware.ts, product-routes.ts, order-routes.ts, customer-routes.ts, other-routes.ts, graphql-schema.ts, websocket.ts, grpc-services.ts, event-bus.ts, openapi-spec.ts.

REST Endpoints and Route Map#

The OpenAPI 3.1 spec (openapi-spec.ts) is the published REST contract, served at /openapi.json. Base path /v1. FREYA_API_ROUTES enumerates the route map. OpenAPI servers are https://api.freya.oshun.ai/v1 (production), https://api.staging.freya.oshun.ai/v1 (staging), and http://localhost:3500/v1 (local).

Route group Path Notes
Health /health GET, unauthenticated readiness check
Products /v1/products GET list, POST create (bearer auth)
Products /v1/products/{id} GET by ID
Orders /v1/orders POST place order (bearer auth)
Orders /v1/orders/{id} GET by ID (bearer auth)
Customers /v1/customers POST register
Customers /v1/customers/{id} GET profile (bearer auth)
Collections /v1/collections Collection route group
Brands /v1/brands Brand route group
Manufacturing /v1/manufacturing Production-order route group
Quality /v1/quality AQL/GMP inspection route group
Inventory /v1/inventory Real-time inventory route group
Formulations /v1/formulations Beauty/personal-care formulation route group
Academy /v1/academy Student/course route group
Webhooks /v1/webhooks/{paystack,stripe,flutterwave,shipping,social} API-key authenticated
GraphQL /graphql GraphQL endpoint
WebSocket /ws Real-time channel

REST Authentication and Authorization (middleware.ts)#

Two security schemes are enforced. bearerAuth uses JWT for user-facing calls; apiKey (the X-API-Key header) is used for service-to-service calls and webhook validation.

UserRole is one of customer, associate, manager, admin. authMiddleware validates a three-part bearer token, checks required claims (userId, email, role), enforces expiresAt, and rejects unknown roles.

ROLE_PERMISSIONS defines what each role can do:

  • customerproducts:read, orders:create, orders:read:own, customer:read:own, customer:update:own, loyalty:read:own, loyalty:redeem:own, cart:manage:own, wishlist:manage:own, reviews:create.
  • associateproducts:read, orders:read, inventory:read, customer:read, clienteling:manage, transactions:create, store:read.
  • manager — adds products:write, orders:update, inventory:manage, reports:read, staff:read, store:manage, manufacturing:read, manufacturing:write, analytics:read.
  • admin — wildcard * (full access).

rbacMiddleware enforces :own permissions with an ownership check: the requesting user must match the resource owner. Rate limiting (RATE_LIMITS) uses three buckets: api allows 100 requests/60 s, auth 10/60 s, webhooks 1000/60 s; rateLimitMiddleware returns retryAfterMs when a window is exhausted.

REST Request/Response Schemas#

Two Zod schema sets exist. The API app's own schemas.ts backs the handler logic directly. @freya/contracts holds the cross-service contract schemas consumed by any other domain calling Freya.

apps/freya/api/src/schemas.ts defines, among others: CreateProductSchema/UpdateProductSchema/SearchProductsSchema, CreateOrderSchema (with paymentMethod of card/mobile_money/ bank_transfer and market of ghana/nigeria/uk/eu/us), UpdateOrderStatusSchema, ProcessReturnSchema, ProcessRefundSchema, RegisterCustomerSchema, UpdateProfileSchema, UpdatePreferencesSchema, RedeemPointsSchema (points must be a positive multiple of 100), CreateManufacturingOrderSchema (priority RUSH/STANDARD/DEFERRED), ScheduleOrderSchema, UpdateBatchSchema, RecordQualityCheckSchema (defect class CRITICAL/MAJOR/MINOR), ScheduleMaintenanceSchema, RecordTransactionSchema, LookupInventorySchema, RequestTransferSchema, CreateCampaignSchema, AddInfluencerSchema, TrackCampaignMetricsSchema, CreateFormulationSchema, AddIngredientSchema, ScheduleStabilityTestSchema, GetTrendReportSchema, GetFinancialReportSchema, and webhook schemas (PaystackWebhookSchema, StripeWebhookSchema, ShippingUpdateSchema, SocialCommerceWebhookSchema).

@freya/contracts (libs/contracts/freya/src) defines four schema modules:

  • product-schemas.tsProductStatusSchema (draft, active, archived, out_of_stock, discontinued), ProductCategorySchema (fashion, textiles, beauty, skincare, haircare, fragrance, jewelry, footwear, eyewear, accessories, home_decor, luggage, personal_care, detergent), MarketSchema (GH, NG, KE, ZA, UK, US, EU, CA, AU, GLOBAL), PriceSchema, ProductVariantSchema, CreateProductRequestSchema, UpdateProductRequestSchema, ProductSearchRequestSchema, ProductResponseSchema.
  • order-schemas.tsOrderStatusSchema (pending, confirmed, processing, shipped, delivered, cancelled, refunded, return_requested, returned), ShippingAddressSchema, OrderLineSchema, CreateOrderRequestSchema, UpdateOrderStatusRequestSchema, OrderResponseSchema.
  • customer-schemas.tsCustomerSegmentSchema (vip, premium, regular, new, diaspora, wholesale, corporate), LoyaltyTierSchema (bronze, silver, gold, platinum, diamond), RegisterCustomerRequestSchema, UpdateCustomerRequestSchema, CustomerPreferencesSchema, CustomerResponseSchema.
  • manufacturing-schemas.tsManufacturingOrderStatusSchema (planned, in_progress, quality_check, completed, on_hold, cancelled), BusinessUnitSchema (eighteen values matching freya_business_unit), CreateManufacturingOrderRequestSchema, QualityInspectionRequestSchema, ManufacturingOrderResponseSchema.

REST Order State Machine (order-routes.ts)#

The customer-order handler enforces a strict status state machine for orders flowing through the REST API. This is the public-API order lifecycle, separate from the ecommerce DTC fulfillment machine and the factory-floor machine.

OrderStatus is PLACED, CONFIRMED, SHIPPED, DELIVERED, RETURNED, CANCELLED. Legal transitions:

From To
PLACED CONFIRMED, CANCELLED
CONFIRMED SHIPPED, CANCELLED
SHIPPED DELIVERED
DELIVERED RETURNED
RETURNED — (terminal)
CANCELLED — (terminal)

handleProcessReturn rejects returns on any order not in DELIVERED. handleProcessRefund rejects a refund amount exceeding the order total. computeOrderTotals applies 15% tax and free domestic shipping for Ghana/Nigeria orders ≥ GHS 500 (otherwise GHS 30 domestic, GHS 150 international).

GraphQL API (graphql-schema.ts)#

FREYA_GRAPHQL_TYPEDEFS is a schema-first SDL definition. It mirrors the REST surface but adds real-time subscription and connection-based pagination.

Enums: BusinessUnit (eighteen values), ProductStatus (eight values matching freya_product_status), Season, Market, OrderStatus, LoyaltyTier. Object types include Product, ProductVariant, Collection, Brand, InventoryLevel, Customer, Order, OrderLine, TrendSignal, Relay-style connection/edge types, and PageInfo. Queries cover product/collection/brand lookup and listing, inventory levels, customer lookup, order lookup, and trending signals. Mutations cover createProduct, updateProductStatus, createOrder, updateOrderStatus, cancelOrder, registerCustomer, updateCustomerProfile, addLoyaltyPoints, cart operations (addToCart, removeFromCart, updateCartQuantity), and inventory operations (reserveInventory, releaseInventory). Subscriptions are inventoryUpdated, orderStatusChanged, trendSignalReceived, and storeKpiUpdated. encodeCursor/decodeCursor implement base64 offset cursors.

gRPC Services (grpc-services.ts)#

gRPC is used for the five internal high-throughput service calls that need lower overhead than HTTP/REST. FREYA_GRPC_PACKAGE is freya.internal, version v1. The five services are defined as GrpcServiceDefinition records:

  • InventoryServiceCheckInventory, BatchCheckInventory, ReserveInventory (TTL-based, idempotent), ReleaseReservation, StreamInventoryUpdates (server streaming).
  • ManufacturingServiceGetManufacturingOrder, ListManufacturingOrders, UpdateManufacturingStatus, StreamProductionEvents (server streaming).
  • QualityServiceEvaluateQualityGate (AQL-based gate evaluation).
  • PricingServiceGetPricing (final price with promotions, loyalty, market pricing).
  • CustomerServiceGetCustomerProfile, AdjustLoyaltyPoints (transactional earn/redeem).

generateProtoStub scaffolds a proto3 service definition from each GrpcServiceDefinition. ReleaseReservationRequest.reason is one of order_confirmed, order_cancelled, expired. QualityGateResponse.nextAction is one of release, rework, scrap, retest.

WebSocket API (websocket.ts)#

The WebSocket server at /ws carries three categories of real-time message: inventory updates for live stock counts, auction bidding for limited-edition drops, and collaborative design sessions in the studio app.

WsMessageType enumerates subscribe, unsubscribe, inventory_update, order_status, bid_placed, auction_ended, price_alert, collaboration_join, collaboration_cursor, collaboration_change, store_kpi, trend_signal, error, ping, pong. WsChannel is one of inventory, orders, auctions, collaboration, store_kpis, trends. Typed payloads exist for each message type: InventoryUpdatePayload, OrderStatusPayload, BidPayload, AuctionEndedPayload, CollaborationCursorPayload, CollaborationChangePayload, StoreKpiPayload, TrendSignalPayload. WS_CONFIG sets a 30-second ping interval, 10-second pong timeout, 20 subscriptions per connection, 64 KB max message size, and a 100-message backpressure queue. buildReservationResult produces an InventoryReservationResult whose failureReason is one of insufficient_stock, already_reserved, product_discontinued.

Domain Events (event-bus.ts)#

Freya domain events follow the CloudEvents 1.0 envelope. The DomainEvent<T> type carries: specversion, id, source, type, datacontenttype, optional dataschema, subject, time, data, optional correlationId, businessUnit, market. Events are published to Kafka topics and consumed by subscribing services inside and outside the Freya domain.

FreyaEventType enumerates the full event vocabulary, organized by family:

  • Productfreya.product.created, freya.product.updated, freya.product.status_changed, freya.product.discontinued.
  • Inventoryfreya.inventory.stocked, freya.inventory.reserved, freya.inventory.released, freya.inventory.depleted, freya.inventory.reorder_triggered.
  • Ordersfreya.order.placed, freya.order.confirmed, freya.order.processing, freya.order.shipped, freya.order.delivered, freya.order.cancelled, freya.order.refunded, freya.order.return_requested.
  • Manufacturingfreya.manufacturing.order_created, freya.manufacturing.started, freya.manufacturing.batch_completed, freya.manufacturing.quality_passed, freya.manufacturing.quality_failed, freya.manufacturing.completed, freya.manufacturing.cancelled.
  • Qualityfreya.quality.inspection_scheduled, freya.quality.inspection_completed, freya.quality.corrective_action_required.
  • Customersfreya.customer.registered, freya.customer.segment_changed, freya.customer.loyalty_tier_changed, freya.customer.vip_granted, freya.customer.points_earned, freya.customer.points_redeemed.
  • Trendsfreya.trend.signal_detected, freya.trend.reached_mainstream, freya.trend.declining.
  • Collectionsfreya.collection.created, freya.collection.launched, freya.collection.sold_out.
  • Academyfreya.academy.student_enrolled, freya.academy.student_graduated, freya.academy.certification_issued.
  • Formulationsfreya.formulation.approved, freya.formulation.rejected, freya.formulation.batch_released.
  • Retailfreya.retail.store_opened, freya.retail.daily_close, freya.retail.kpi_updated.
  • Paymentsfreya.payment.succeeded, freya.payment.failed, freya.payment.refunded.

FREYA_EVENT_TOPICS maps event types to six Kafka topics: freya.orders, freya.inventory, freya.production, freya.quality, freya.customers, freya.trends; resolveEventTopic falls back to freya.misc for unmapped types. FREYA_DLQ_TOPIC is freya.dlq.

Defined payload interfaces capture the data that crosses service boundaries: ProductCreatedEventData, OrderPlacedEventData (includes orderId, orderNumber, customerId, market, channel, currency, totalAmount, lineCount, lines, paymentReference), OrderShippedEventData, InventoryReservedEventData (includes reservationToken, expiresAt), InventoryDepletedEventData, ManufacturingBatchCompletedEventData, QualityInspectionCompletedEventData (result of passed/failed/conditional_pass/pending_retest, nextAction of release/rework/scrap/retest), CustomerLoyaltyTierChangedEventData, TrendSignalDetectedEventData, FormulationApprovedEventData.

buildFreyaEventBusConfig reads FREYA_KAFKA_BROKERS/KAFKA_BROKERS (default localhost:9092), defaults producer acks to -1 (all replicas — important for orders and payments), and uses snappy compression. FREYA_CONSUMER_CONFIGS defines consumer groups per service role: freya-ecommerce consumes freya.orders/freya.inventory/freya.customers; freya-manufacturing consumes freya.orders/freya.production/freya.quality; freya-retail consumes freya.inventory/freya.customers/freya.trends; freya-trend-worker consumes freya.trends.

Capability Libraries#

Each capability library is deterministic, domain-specific business logic — not generic CRUD. Libraries depend on @freya/core for shared types and never on each other. State machines in every library are enforced with explicit transition tables that throw on illegal transitions.

@freya/fashion — Apparel Design Pipeline#

Source modules: design-pipeline.ts, collection-planner.ts, size-grading.ts, trend-forecasting.ts, production-scheduler.ts, african-print-library.ts.

Design pipeline state machine (DesignPipeline). Every style moves through a controlled set of stages, each of which has defined entry requirements. DesignStage is concept, mood_board, sketch, pattern, prototype, sample, production, discontinued. transitionTo throws on any unlisted transition and appends a timestamped entry to history.

From To
concept mood_board, discontinued
mood_board sketch, concept, discontinued
sketch pattern, mood_board, discontinued
pattern prototype, sketch, discontinued
prototype sample, pattern, discontinued
sample production, prototype, discontinued
production discontinued
discontinued — (terminal)

ApprovalStatus (used by sketches and design approvals) is pending, approved, rejected, revision_required.

Other classes in this library: ConceptBoardManager, SketchManager (versioned sketches), PatternMaker (default 1.5 cm seam allowance, marker utilization estimation), PrototypingTracker (capped at MAX_REVISION_CYCLES = 5), TechPackGenerator (emits a TechPack with a six-row XS–XXL measurements table, BOM, construction details, and labeling specs; validate checks required fields), DesignApprovalWorkflow (multi-stakeholder sign-off — required roles designer, merchandiser, qa, director; overall status derived from all sign-offs), DesignAssetManager (AssetType of sketch/photo/3d/flat), and DesignCostEstimator (30% overhead rate, SMV-based labor costing).

Collection planning. CollectionStatus is concept, design, production, launched, archived. SEASON_CALENDAR defines per-season show months, delivery months, and milestone offsets for SS, FW, Resort, PreFall, and Capsule. CapsuleCollectionBuilder enforces MAX_STYLES = 12. CollectionBudgetPlanner applies a 2.2× wholesale markup and 2.4× retail-on-wholesale markup, and enforces a minimum 60% gross margin (marginCompliant). CollectionPresentationBuilder requires 6–12 looks.

@freya/textiles — Dyeing, Printing, Finishing#

Source modules: dye-management.ts, print-operations.ts, finishing-operations.ts, vertical-integration.ts.

dye-management.ts models dye recipes (DyeClass of reactive, acid, disperse, vat, direct), a dye-process state machine (DyePhase of loading, heating, dyeing, rinsing, unloading), color matching against Lab color values, dye-consistency SPC control limits, water-usage optimization, chemical inventory with HazardClass 1–9, African natural-dye formulation (NaturalDyeFormulator), and effluent compliance monitoring (EffluentParameter of COD, BOD, pH, color_ADMI, TDS).

print-operations.ts models a wax print state machine, digital/screen/block printing, print design preparation, and print costing. finishing-operations.ts models finishing processes (sanforizing, calendering, mercerizing, softening, anti-shrink), DWR water repellency (DWRChemistry from C8_PFAS through C0_bio), wrinkle resistance, a fabric-testing lab, and a finishing quality gate.

vertical-integration.ts models make-vs-buy analysis, spinning/weaving/knitting operations, capacity planning, textile cost modeling, waste reduction, Kente weave preservation (KENTE_COLOR_MEANINGS), and a sustainability scorecard.

@freya/beauty — Skincare, Cosmetics, Fragrance, Haircare#

Source modules: skincare-formulation.ts, cosmetics-development.ts, fragrance-development.ts, haircare-development.ts, personal-care-detergent.ts, stability-regulatory.ts.

skincare-formulation.ts models a formulation lifecycle, shea-butter and cocoa-butter grade management (SheaButterGrade, CocoaButterType), an African botanical library, a formulation incompatibility checker (IncompatibilitySeverity of mild/moderate/severe), emulsion HLB calculation (EmulsionType W/O/O/W), preservative-system design, an SPF calculator over a UV-filter library, and batch costing.

cosmetics-development.ts models a cosmetics development pipeline with STAGE_DELIVERABLES, shade-range design (Undertone of cool/neutral/warm/olive), lip and eye product formulation, packaging design, product naming, and launch planning.

fragrance-development.ts models the fragrance pyramid (FragranceNoteClass top/heart/base with evaporation profiles), an African scents library, perfume concentration specs (PerfumeConcentration), and fragrance blending. haircare-development.ts and personal-care-detergent.ts cover Afro-textured haircare and personal-care/detergent formulation respectively. stability-regulatory.ts covers stability testing protocols and regulatory submission logic across Ghana FDA, NAFDAC, EU SCCS, and US FDA.

@freya/ecommerce — Catalog, Cart, Checkout, Diaspora DTC#

Source modules: catalog-inventory.ts, social-personalization.ts, diaspora-commerce.ts.

Ecommerce order state machine (catalog-inventory.ts). This is the DTC fulfillment lifecycle, separate from the REST API's customer-order machine. OrderStatus has fourteen values: placed, payment_confirmed, processing, picked, packed, shipped, out_for_delivery, delivered, return_requested, return_approved, returned, refund_processing, refunded, cancelled.

Other enums and classes in this module: PaymentGateway (paystack, flutterwave, stripe), PaymentMethod (includes mtn_momo, vodafone_cash, bank_card, bank_transfer, ussd, card, apple_pay, google_pay), ShippingCarrier (DHL, FedEx, UPS), CheckoutStep (cart_review, address, shipping, payment, confirmation). Classes include ProductCatalogService, CartManager, CheckoutOrchestrator, PaymentProcessor, OrderManagementService, InventoryService (over a fixed WAREHOUSES set), WishlistService, ReviewService, and SearchEngine.

diaspora-commerce.ts models diaspora markets (DiasporaCountry), multi-currency management, international shipping calculation, customs document generation, diaspora pricing strategy, localized content (Language en/fr), and international returns. social-personalization.ts models social commerce, a product recommendation engine, customer segmentation (BehavioralSegment of vip, loyal, at_risk, new, dormant, one_time), email-marketing automation (EmailFlowType), a subscription-box manager (SubscriptionTier of essentials/luxe/heritage), abandoned-cart recovery, a customer lifetime-value model, a loyalty-program engine (LoyaltyTierName from bronze to obsidian), and virtual try-on integration (TryOnProductType).

@freya/manufacturing — Production Execution#

Source modules: cosmetics-manufacturing.ts, textile-manufacturing.ts, assembly-manufacturing.ts, cross-manufacturing.ts.

cosmetics-manufacturing.ts models a cosmetics manufacturing stage machine, clean-room management (CleanRoomISO ISO7/ISO8), BatchScale of lab, pilot, commercial, mixing-process control, filling lines (FillingLineType of tube/jar/pump_bottle), batch records, in-process quality testing, and a detergent manufacturing line (DetergentProductionMethod of spray_drying, agglomeration, liquid_mixing).

cross-manufacturing.ts models machine utilization (OEE — OEELossCategory), production cost analysis, lean manufacturing (MudaType waste categories), capacity planning, equipment maintenance (MaintenanceType of preventive/predictive/corrective), manufacturing compliance (ComplianceStandard of ISO9001, ISO22716, ISO14001, ISO45001, OHSAS18001), waste management, and energy management (EnergySource of grid/solar/generator).

textile-manufacturing.ts models textile production lines (ProductionLineStatus of idle, setup, running, maintenance, breakdown), loom scheduling (LoomType of shuttle/rapier/air_jet), dye-house planning, textile waste tracking, and maintenance scheduling. assembly-manufacturing.ts models per-product-type assembly stage machines for watches, jewelry, eyewear, footwear, and leather goods, plus a component inventory manager.

@freya/retail — Store Operations and Clienteling#

Source modules: store-operations.ts, customer-experience.ts, portfolio-management.ts.

store-operations.ts models a fixed StoreId set (accra_osu, accra_mall, kumasi_garden_city, lagos_victoria_island), opening/closing checklists (ChecklistStage, ChecklistItemStatus of pending/in_progress/ completed/issue), visual merchandising by StoreZone, store inventory management (StockCategory of fashion/beauty/jewelry), sales analytics, staff scheduling and performance tracking, POS integration (PaymentMethod of cash/card/MoMo), customer-traffic analysis, and store maintenance (MaintenanceUrgency of routine/urgent/emergency).

customer-experience.ts models in-store personalization, a clienteling tool, VIP experience management (VIPService), in-store try-on tracking (TryOnOutcome of purchased/not_purchased/size_exchange), and customer feedback (NPSClassification of promoter/passive/detractor).

@freya/brand — Brand Architecture and Storytelling#

Source modules: brand-architecture.ts, heritage-storytelling.ts, digital-presence.ts.

brand-architecture.ts models brand relationship structures (BrandRelationshipType of master/endorsed/sub), a brand positioning map, brand-guideline management, brand-equity measurement, sub-brand creation, brand-consistency auditing, brand-extension evaluation, and co-branding opportunity identification.

heritage-storytelling.ts models a heritage story engine, artisan story capture, a cultural calendar manager, a provenance story builder (NarrativeComponent, LuxuryPillar), and luxury positioning strategy. digital-presence.ts models social-media monitoring (SocialChannel), brand-sentiment analysis, influencer management (InfluencerTier of nano/micro/macro/mega), PR coverage tracking, diaspora brand perception (DiasporaMarketKey), content-calendar planning, UGC curation, and competitor brand tracking.

@freya/academy — Curriculum and Certification#

Source modules: curriculum.ts, curriculum-internals.ts, course-management (academy-operations.ts), student-management.ts.

CourseLevel is certificate, diploma, degree. BloomsTaxonomyLevel models the cognitive taxonomy used for learning outcome design. Classes include CurriculumDesigner, CourseManager, ModuleBuilder, and three specialized curriculum builders: AfricanFashionCurriculum, SustainableFashionCurriculum, BusinessFashionCurriculum. student-management.ts manages student records and progression.

@freya/jewelry — Ethical Gold Jewelry#

Source modules: jewelry-production.ts, gold-management.ts, craft-preservation.ts. This library focuses heavily on provenance: it covers gold sourcing and management with full chain-of-custody tracking, jewelry production processes, hallmarking, and craft preservation with artisan heritage records.

@freya/market-intel — Trend and Competitive Intelligence#

Source modules: trend-monitoring.ts, competitive-intelligence.ts, market-research.ts. Models trend monitoring (ingesting runway, social, and sales-data signals), competitive intelligence (CompetitorMove), and market research. Outputs feed into @freya/financials and @freya/brand.

@freya/financials — Unit Economics and Investment#

Source modules: unit-economics.ts, financial-planning.ts, startup-investment.ts. FreyaBusinessUnit enumerates the financed business units. InvestmentScale is pilot, standard, flagship. Classes include StartupCostModeler, PhaseInvestmentPlanner, FundingStructureOptimizer, EquipmentCapexPlanner, FacilityInvestmentModeler (FacilityType, Location), and ROIProjector. DepreciationMethod is straight_line or declining_balance.

@freya/connectors — Cross-Domain Integration#

Source modules: asase-connectors.ts, brigid-connectors.ts, cybele-connectors.ts, saraswati-connectors.ts, maat-connectors.ts. This library is the sole point where Freya's shapes are translated to other domains' contracts, keeping all cross-domain coupling in one place.

  • Asase (agriculture, task 57.14.1) — SheaButterSupplyChain, CocoaButterProcurement, NaturalIngredientTraceability, CottonSupplyChain, IngredientQualitySync, FairTradeCertification.
  • Brigid (manufacturing automation, 57.14.2) — TextileAutomation, CosmeticsPackagingAutomation, QualityVisionSystem, SmartPackaging, PredictiveMaintenanceSync.
  • Cybele (construction, 57.14.3) — FlagshipStoreDesign, RetailSpacePlanning, FactoryConstruction, InteriorTextileSupply.
  • Saraswati (logistics, 57.14.4) — EcommerceLogistics, IoTRetailSensors, SmartWarehouse, EVDeliveryFleet.
  • Maat (strategic intelligence, 57.14.5) — FreyaDashboardSync, BrandAnalyticsFeed, FinancialConsolidation, MarketIntelligenceFeed.

@freya/sota — State-of-the-Art Enhancements#

Source modules: ai-design.ts, ai-analytics.ts, computer-vision.ts, nlp.ts, blockchain-auth.ts, virtual-tryon.ts. This library houses the Phase 57 state-of-the-art layer: AI-assisted design and generative collection ideation, AI analytics, computer-vision quality control, NLP, blockchain-based authenticity verification, and virtual try-on. Each is delivered as an opt-in enrichment over the deterministic capability libraries — the business logic does not depend on them and remains testable in isolation.

Single-Module Business-Unit Libraries#

Eleven libraries each ship a single src/index.ts module, owning their business-unit logic: @freya/watches, @freya/perfumes, @freya/bridal-events, @freya/hair-care, @freya/home-decor, @freya/footwear, @freya/eyewear, @freya/luggage-leather, @freya/personal-care, @freya/cleaning-products, @freya/textile-finishing. (@freya/textile-finishing's index.ts models textile production lines, loom scheduling, dye-house planning, waste tracking, energy monitoring, and maintenance scheduling.)

Applications#

Five applications under apps/freya/* compose user workflows over the capability libraries. Each ships a thin set of view/orchestration modules. Applications depend on capability libraries but not on each other; cross-app coordination goes through the API service and the event bus.

  • apps/freya/api — documented in full in the API Surface section above.
  • apps/freya/studio — design and brand studio. Source modules: trend-board.ts, collection-dashboard.ts, design-workspace.ts, design-approval-board.ts, tech-pack-editor.ts, textile-library.ts, color-palette-studio.ts.
  • apps/freya/shop — DTC storefront. Source modules: product-listing.ts, product-detail.ts, shopping-cart.ts, checkout-flow.ts, customer-account.ts, subscription-box.ts, virtual-tryon.ts.
  • apps/freya/retail — retail-operations app. Source modules: store-dashboard.ts, clienteling-app.ts, inventory-lookup.ts, staff-performance.ts, visual-merchandising.ts.
  • apps/freya/manufacturing — factory-floor app. Source modules: order-management.ts, production-dashboard.ts, batch-record-manager.ts, quality-inspection.ts, equipment-dashboard.ts, waste-reporting.ts.

Manufacturing-App Order State Machine (order-management.ts)#

The factory-floor app enforces its own strict linear state machine over manufacturing orders. This is separate from the supply-chain OrderStatus in @freya/core and the ecommerce DTC machine in @freya/ecommerce.

OrderStatus is DRAFT, SCHEDULED, IN_PROGRESS, QC, COMPLETE, SHIPPED. OrderPriority is RUSH, STANDARD, DEFERRED.

Method Requires status Sets status
createOrder DRAFT
scheduleOrder DRAFT SCHEDULED
startProduction SCHEDULED IN_PROGRESS
moveToQC IN_PROGRESS QC
completeOrder QC COMPLETE
shipOrder COMPLETE SHIPPED

assertStatus throws if an order is not in the expected status, preventing out-of-sequence transitions. A RUSH priority applies the RUSH_PREMIUM_MULTIPLIER of 2.0 to the order's total cost.

Configuration and Environment Inputs#

The following environment variables control all infrastructure connections. Every variable has a fallback so the system runs locally without extra configuration.

Variable Consumed by Default
FREYA_DATABASE_URL / DATABASE_URL connection.ts, FREYA_DRIZZLE_CONFIG postgresql://oshun:oshun_dev@localhost:5432/freya
FREYA_DATABASE_REPLICA_URLS buildReadReplicaConfig empty (no replicas)
FREYA_USE_PGBOUNCER buildFreyaDbPoolConfig false
PGBOUNCER_PORT buildPgBouncerUrl 6432
FREYA_REDIS_URL / REDIS_URL buildFreyaRedisConfig redis://localhost:6379
FREYA_S3_ENDPOINT / S3_ENDPOINT buildFreyaS3Config http://localhost:9000
FREYA_S3_REGION / S3_REGION buildFreyaS3Config us-east-1
FREYA_S3_ACCESS_KEY / S3_ACCESS_KEY buildFreyaS3Config minioadmin
FREYA_S3_SECRET_KEY / S3_SECRET_KEY buildFreyaS3Config minioadmin
FREYA_CDN_BASE_URL buildFreyaS3Config http://localhost:9000/freya-product-imagery
FREYA_S3_BUCKET_DESIGN / _PRODUCTS / _MANUFACTURING FREYA_S3_BUCKETS freya-design-assets / freya-product-imagery / freya-manufacturing-docs
FREYA_KAFKA_BROKERS / KAFKA_BROKERS buildFreyaEventBusConfig localhost:9092
FREYA_KAFKA_CLIENT_ID buildFreyaEventBusConfig freya-producer
FREYA_KAFKA_GROUP_ID event-bus producer/consumer config freya-producers
FREYA_KAFKA_GROUP_ID_ORDERS / _MANUFACTURING FREYA_CONSUMER_CONFIGS freya-orders-consumer / freya-manufacturing-consumer

Requirements and Invariants#

These six requirements are enforced by code or mandated by features.md for any change touching the relevant data. They are not optional — violating any of them can result in regulatory exposure, data loss, or financial errors.

  1. Provenance and certification evidence. Material, Supplier, Artisan, and freya_materials records retain source country/region and certifications. Jewelry and gold provenance records retain full source and certification evidence permanently. freya_quality_inspections retains certificate_url, defect detail, and corrective actions.

  2. Idempotent commerce. Inventory reservation is TTL-based and idempotent (gRPC ReserveInventory accepts a reservationToken for idempotent checks; InventoryReservedEventData carries a reservationToken). Order and inventory updates must not double-create or double-decrement on a retried webhook or sync event. Cart and inventory state is held in Redis with distributed locks (freya:lock:inv:{variantId}, freya:lock:checkout:{orderId}).

  3. Beauty audit trails and formulation versioning. Formulation carries a version; freya_formulations uses a (code, version) unique pair so a formulation change creates a new version rather than mutating the prior one. Stability and regulatory records are append-only evidence. Beauty product efficacy_claims are stored with their evidence type and study reference.

  4. Privacy and role-based access. freya_customers carries marketing_consent, data_processing_consent, and consents_updated_at. freya_virtual_tryon_sessions.body_photo_url is ephemeral and deleted after the session. The API enforces UserRole-based RBAC with :own ownership checks (middleware.ts).

  5. State-machine integrity. Order and design state machines reject illegal transitions: the REST customer-order machine, the ecommerce DTC fulfillment machine, the manufacturing-app OrderManagement machine, the fashion DesignPipeline, and the various per-product-type assembly machines all use explicit transition tables and throw on violation.

  6. Quality gating. A failed AQL inspection (evaluateQualityResult returning fail) blocks order release; QualityGateResponse.nextAction drives the release/rework/scrap/retest decision.

Domain Boundaries#

Freya owns luxury-goods business operations and product supply. It does not own personal consumer styling, virtual try-on as a consumer feature, or individual recommendation decisions — those belong to Aglaea. Freya publishes products, textiles, sizing, retail inventory, brand campaigns, and provenance records; Aglaea consumes them for consumer recommendation and shopping experiences. Stores, factories, and real-estate facilities belong to Cybele; factory-automation machinery belongs to Brigid; advanced technology-product manufacturing belongs to Saraswati. The @freya/connectors library is the sole integration boundary to Asase, Brigid, Cybele, Saraswati, and Maat — no capability library imports from those domains directly.

Verification Expectations#

Changes run package tests for affected libraries and apps (Vitest — every library has a vitest.config.ts and a *.spec.ts suite). Commerce, payment, inventory, manufacturing, and customer-data changes additionally require contract and persistence regression coverage. Tests must assert specific computed values against known-correct answers; asserting only shape or truthiness is not sufficient for the domain's financial, quality, and formulation logic.