# Freya Domain - Technical Specifications

> 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`.
- **`FashionSeason`** — `SS` (Spring/Summer), `FW` (Fall/Winter), `Resort`,
  `PreFall`, `Capsule`, `Perennial`.
- **`FreyaCurrency`** — `GHS`, `NGN`, `USD`, `GBP`, `EUR`, `CAD`, `ZAR`.
- **`MarketRegion`** — `Ghana`, `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 (`Ghana`→`GHS`,
`Nigeria`→`NGN`, `UK`→`GBP`, `USA`→`USD`, `Canada`→`CAD`,
`Germany`/`Netherlands`→`EUR`, `Pan_Africa`→`GHS`).

### 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:

- **`FiberType`** — `cotton`, `silk`, `wool`, `polyester`, `viscose`, `bamboo`,
  `hemp`, `kente_silk`, `ashanti_cotton`, `linen`, `nylon`, `acrylic`, `lurex`.
- **`TextileFinish`** — `wax_print`, `batik`, `tie_dye`, `digital_print`,
  `screen_print`, `embroidery`, `beading`, `smocking`, `applique`, `plain`.
- **`AfricanPrintType`** — `Ankara`, `Kente`, `Adinkra`, `Bogolan`, `Shweshwe`,
  `Aso_Oke`, `Kuba`, `Brocade`.
- **`LeatherType`** — `full_grain`, `top_grain`, `genuine`, `bonded`,
  `vegan_pu`, `vegan_cork`, `suede`.
- **`MaterialGradeScore`** — `A+`, `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:

- **`SupplierTier`** — `tier_1`, `tier_2`, `tier_3`.
- **`SupplierCertification`** — `ISO9001`, `OEKO_TEX`, `GOTS`, `Fairtrade`,
  `SEDEX`, `SA8000`, `WRAP`, `FSC`.
- **`OrderStatus`** (supply-chain order) — `draft`, `placed`, `confirmed`,
  `in_production`, `quality_check`, `ready`, `shipped`, `delivered`,
  `cancelled`.
- **`InspectionResult`** — `pass`, `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:

- **`CustomerSegment`** — `fashionista`, `conscious_consumer`,
  `heritage_seeker`, `luxury_buyer`, `diaspora_elite`, `mass_market`.
- **`LoyaltyTier`** — `bronze`, `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:

- **`FragranceFamily`** — `floral`, `oriental`, `woody`, `fresh`, `fougere`,
  `chypre`, `gourmand`, `aquatic`.
- **`HairType`** — the twelve Andre Walker classes `1A`–`4C`.
- **`SkinType`** — `normal`, `dry`, `oily`, `combination`, `sensitive`,
  `mature`.
- **`FitzpatrickScale`** — numeric `1`–`6`.
- **`FormulationStatus`** — `concept`, `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 generation** — `generateSKU(buCode, category, year, sequence)` builds
  `FSKU-{BU}-{CAT}-{YY}-{SSSS}` using a fixed category→3-letter abbreviation map
  (`fashion_rtw`→`RTW`, `jewelry`→`JWL`, etc.).
- **Barcodes** — `generateEAN13`/`validateEAN13Checksum` and
  `generateUPCA`/`validateUPCAChecksum` implement the standard EAN-13 and UPC-A
  check-digit algorithms.
- **Currency** — `EXCHANGE_RATES_TO_GHS` holds fixed GHS conversion rates for
  every `FreyaCurrency`; `convertToGHS`, `convertFromGHS`, and `formatCurrency`
  (with per-currency symbols) operate on it.
- **Textile conversions** — `yardsToMeters`, `metersToYards`,
  `gsmToOzPerSqYard`, `denierToTex`, `threadCountToGSM`.
- **Pantone matching** — `GHANA_FASHION_PALETTE` is a twelve-color Kente/Ankara
  palette; `findNearestPantone` returns the closest palette color by simplified
  Delta-E distance.
- **Error types** — `FreyaError` (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_status` — `concept`, `in_development`, `sampling`,
  `pre_production`, `in_production`, `ready_to_ship`, `active`, `discontinued`.
- `freya_business_unit` — `fashion`, `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_season` — `SS`, `FW`, `Resort`, `PreFall`, `Capsule`, `Bridal`,
  `Couture`.
- `freya_collection_type` — `seasonal`, `capsule`, `collaboration`,
  `limited_edition`, `bridal`, `couture`.
- `freya_material_type` — `textile`, `leather`, `metal`, `gemstone`,
  `botanical`, `chemical`, `synthetic`.
- `freya_fiber_type` — `cotton`, `silk`, `wool`, `polyester`, `viscose`,
  `bamboo`, `hemp`, `linen`, `kente_silk`, `local_cotton`, `cashmere`, `mohair`,
  `lyocell`, `nylon`, `acrylic`.
- `freya_textile_finish` — `wax_print`, `batik`, `tie_dye`, `digital_print`,
  `screen_print`, `embroidery`, `beading`, `smocking`, `applique`, `laser_cut`,
  `pleating`, `quilting`, `burnout`.
- `freya_order_status` — `pending`, `confirmed`, `processing`, `shipped`,
  `delivered`, `cancelled`, `refunded`, `return_requested`, `returned`.
- `freya_manufacturing_status` — `planned`, `in_progress`, `quality_check`,
  `completed`, `on_hold`, `cancelled`.
- `freya_quality_result` — `passed`, `failed`, `conditional_pass`,
  `pending_retest`.
- `freya_customer_segment` — `vip`, `premium`, `regular`, `new`, `diaspora`,
  `wholesale`, `corporate`.
- `freya_loyalty_tier` — `bronze`, `silver`, `gold`, `platinum`, `diamond`.
- `freya_currency` — `GHS`, `NGN`, `USD`, `GBP`, `EUR`, `CAD`, `ZAR`, `KES`.
- `freya_market` — `ghana`, `nigeria`, `kenya`, `south_africa`, `uk_diaspora`,
  `us_diaspora`, `canada_diaspora`, `eu_diaspora`.
- `freya_store_type` — `flagship`, `pop_up`, `duty_free`, `mall_kiosk`,
  `market_stall`, `studio`, `warehouse`, `outlet`.
- `freya_inspection_type` — `fabric`, `garment`, `cosmetics`, `jewelry`,
  `packaging`, `finished`, `raw_materials`, `in_process`.
- `freya_certification_status` — `pending`, `approved`, `rejected`, `expired`,
  `under_review`.
- `freya_asset_type` — `logo`, `sketch`, `tech_pack`, `pattern`, `cad`,
  `mood_board`, `product_photo`, `lifestyle_photo`, `video`, `ar_model`.
- `freya_trend_source` — `instagram`, `tiktok`, `pinterest`, `runway`,
  `street_style`, `celebrity`, `editorial`, `trade_show`, `sales_data`,
  `search`.
- `freya_academic_status` — `enrolled`, `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_id` → `freya_brands`, `collection_id` →
  `freya_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_variants`** — `product_id` → `freya_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_collections`** — `name`, `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_materials`** — `code` (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_id` →
  `freya_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_suppliers`** — `code` (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_artisans`** — `code` (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_orders`** — `order_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_customers`** — `email` (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_locations`** — `code` (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_orders`** — `order_number` (unique), `customer_id` →
  `freya_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_id` → `freya_retail_locations` for click-and-collect.
- **`freya_carts`** — `session_id` (unique), `customer_id`, `market`,
  `currency`, `lines` (jsonb), `promo_code`, `discount_amount`, `total_items`,
  `subtotal`, `expires_at`.
- **`freya_wishlists`** — `customer_id` → `freya_customers` (cascade), `name`,
  `is_public`, `share_token`, `items` (jsonb).
- **`freya_virtual_tryon_sessions`** — `customer_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_brands`** — `code` (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_campaigns`** — `brand_id` → `freya_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_partnerships`** — `brand_id` → `freya_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_inspections`** — `inspection_number` (unique), `type`,
  `manufacturing_order_id` → `freya_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_students`** — `student_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_courses`** — `code` (unique), `title`, `programme`, `level`
  (100–400), `credits`, `duration_weeks`, `description`, `learning_outcomes`,
  `prerequisites`, `instructor_id`, `materials_required`, `max_enrollment`.
- **`freya_academy_enrollments`** — `student_id` → `freya_academy_students`
  (cascade), `course_id` → `freya_academy_courses`, `academic_year`, `semester`,
  `grade`, `grade_letter`, `attendance_pct`, `status`, `completed_at`.
- **`freya_formulations`** — `code`+`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_signals`** — `source`, `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_records`** —
  `period_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_valuations`** — `valuation_date`, `business_unit`,
  `product_id` → `freya_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:

- **`customer`** — `products: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`.
- **`associate`** — `products: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.ts`** — `ProductStatusSchema` (`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.ts`** — `OrderStatusSchema` (`pending`, `confirmed`,
  `processing`, `shipped`, `delivered`, `cancelled`, `refunded`,
  `return_requested`, `returned`), `ShippingAddressSchema`, `OrderLineSchema`,
  `CreateOrderRequestSchema`, `UpdateOrderStatusRequestSchema`,
  `OrderResponseSchema`.
- **`customer-schemas.ts`** — `CustomerSegmentSchema` (`vip`, `premium`,
  `regular`, `new`, `diaspora`, `wholesale`, `corporate`), `LoyaltyTierSchema`
  (`bronze`, `silver`, `gold`, `platinum`, `diamond`),
  `RegisterCustomerRequestSchema`, `UpdateCustomerRequestSchema`,
  `CustomerPreferencesSchema`, `CustomerResponseSchema`.
- **`manufacturing-schemas.ts`** — `ManufacturingOrderStatusSchema` (`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:

- **`InventoryService`** — `CheckInventory`, `BatchCheckInventory`,
  `ReserveInventory` (TTL-based, idempotent), `ReleaseReservation`,
  `StreamInventoryUpdates` (server streaming).
- **`ManufacturingService`** — `GetManufacturingOrder`,
  `ListManufacturingOrders`, `UpdateManufacturingStatus`,
  `StreamProductionEvents` (server streaming).
- **`QualityService`** — `EvaluateQualityGate` (AQL-based gate evaluation).
- **`PricingService`** — `GetPricing` (final price with promotions, loyalty,
  market pricing).
- **`CustomerService`** — `GetCustomerProfile`, `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:

- **Product** — `freya.product.created`, `freya.product.updated`,
  `freya.product.status_changed`, `freya.product.discontinued`.
- **Inventory** — `freya.inventory.stocked`, `freya.inventory.reserved`,
  `freya.inventory.released`, `freya.inventory.depleted`,
  `freya.inventory.reorder_triggered`.
- **Orders** — `freya.order.placed`, `freya.order.confirmed`,
  `freya.order.processing`, `freya.order.shipped`, `freya.order.delivered`,
  `freya.order.cancelled`, `freya.order.refunded`,
  `freya.order.return_requested`.
- **Manufacturing** — `freya.manufacturing.order_created`,
  `freya.manufacturing.started`, `freya.manufacturing.batch_completed`,
  `freya.manufacturing.quality_passed`, `freya.manufacturing.quality_failed`,
  `freya.manufacturing.completed`, `freya.manufacturing.cancelled`.
- **Quality** — `freya.quality.inspection_scheduled`,
  `freya.quality.inspection_completed`,
  `freya.quality.corrective_action_required`.
- **Customers** — `freya.customer.registered`, `freya.customer.segment_changed`,
  `freya.customer.loyalty_tier_changed`, `freya.customer.vip_granted`,
  `freya.customer.points_earned`, `freya.customer.points_redeemed`.
- **Trends** — `freya.trend.signal_detected`, `freya.trend.reached_mainstream`,
  `freya.trend.declining`.
- **Collections** — `freya.collection.created`, `freya.collection.launched`,
  `freya.collection.sold_out`.
- **Academy** — `freya.academy.student_enrolled`,
  `freya.academy.student_graduated`, `freya.academy.certification_issued`.
- **Formulations** — `freya.formulation.approved`, `freya.formulation.rejected`,
  `freya.formulation.batch_released`.
- **Retail** — `freya.retail.store_opened`, `freya.retail.daily_close`,
  `freya.retail.kpi_updated`.
- **Payments** — `freya.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.
