Domain · Specifications

Aglaea Domain — Technical Specifications

1.

12sections31 minread

On this page

Aglaea — AI-Powered Fashion, Beauty, and Personal Style Platform

This document specifies the implemented contracts of the Aglaea domain: the foundation type system, domain entities, enumerations, the REST API surface, the domain event system, persistence schemas, and configuration. Every type, enum value, endpoint, and event below is drawn directly from the source under libs/aglaea/.

Aglaea is a pure library domain — it has no apps/aglaea/ or services/aglaea/. It is implemented as 93 libraries under libs/aglaea/.

For a plain-English description of what each library does, see features.md. For how they are layered and wired together, see architecture.md. This document is the definitive contract reference — the source of truth for type shapes, API paths, event strings, and schema field names.


Table of Contents#

  1. Foundation Type System (@aglaea/core)
  2. Core Domain Constants (@aglaea/core)
  3. Configuration (@aglaea/core)
  4. AI Orchestration Types (@aglaea/ai-orchestrator)
  5. REST API Surface (@aglaea/api-services)
  6. Domain Event System (@aglaea/events)
  7. API-Services Event Catalog (@aglaea/api-services)
  8. Persistence Schemas (@aglaea/database)
  9. SDK Surface (@aglaea/sdk)
  10. Technology Stack

1. Foundation Type System (@aglaea/core)#

@aglaea/core (libs/aglaea/core/src/types.ts) is the foundation type system for the domain. Every composite type is defined as a Zod schema with an inferred TypeScript type (z.infer), which means all types are validated at runtime wherever they cross a module boundary. The package depends only on zod, so it can be safely imported by any library in the domain without introducing additional dependency weight.

The index.ts barrel re-exports types, constants, validation, errors, color-science, body-analysis, skin-analysis, hair-analysis, fashion-taxonomy, style-profiling, recommendation-engine, occasion-context, trend-analysis, fabric-intelligence, fragrance-profiling, logging, config, feature-flags, rate-limiting, and caching.

1.1 Branded ID Types#

Aglaea uses five nominal (branded) string types to prevent accidental mixing of IDs across different entity types at compile time. Each is validated against a UUID v4 pattern by its corresponding Zod schema.

Type Schema Purpose
PersonalProfileId PersonalProfileIdSchema Identifier for a personal style profile
WardrobeItemId WardrobeItemIdSchema Identifier for a wardrobe item
OutfitId OutfitIdSchema Identifier for a styled outfit
AnalysisId AnalysisIdSchema Identifier for an analysis session (skin/hair/etc.)
RecommendationId RecommendationIdSchema Identifier for a recommendation

Each schema enforces UUID_V4_PATTERN (^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$) and returns a typed z.ZodType for the branded type.

1.2 Color Science Types#

Colors are stored in multiple spaces simultaneously because different spaces serve different purposes. RGB and Pantone are for display and production output; HSL is for human-readable hue/saturation/lightness reasoning; LAB is the canonical internal space for color-distance calculations and harmony scoring, because LAB is perceptually uniform — equal numeric deltas correspond to equal perceived differences.

Schema Type Fields
RGBSchema RGB r, g, b — integers 0–255 (sRGB color space)
HSLSchema HSL h (0–360 degrees), s (0–100), l (0–100)
LABSchema LAB L (0–100), a (−128 to 127), b (−128 to 127) — CIE L*a*b*, perceptually uniform
CMYKSchema CMYK c, m, y, k — percentages 0–100 (print production)
PantoneColorSchema PantoneColor code (Pantone reference), name, hex (6-digit hex approximation)

The following enums capture color-system concepts used throughout the recommendation engine:

ColorHarmonySchema (ColorHarmony) — color-wheel relationship enum, used to score and label the palette harmony of an outfit recommendation: Complementary, Analogous, Triadic, SplitComplementary, Tetradic, Monochromatic.

SeasonalSubtypeSchema (SeasonalSubtype) — the 12-season color analysis system, which refines the four parent seasons along warmth, value, and chroma axes: LightSpring, WarmSpring, ClearSpring, LightSummer, SoftSummer, CoolSummer, SoftAutumn, WarmAutumn, DeepAutumn, DeepWinter, CoolWinter, ClearWinter.

SeasonSchema (Season) — parent season grouping: Spring, Summer, Autumn, Winter.

SkinUndertoneSchema (SkinUndertone) — Cool, Warm, Neutral, Olive.

ColorTemperatureSchema (ColorTemperature) — Cool, Warm, Neutral.

SeasonalColorPaletteSchema (SeasonalColorPalette) is the primary output of color analysis and the primary input to outfit and accessory recommendations. Its fields are:

Field Type Required Meaning
subtype SeasonalSubtype yes The 12-season subtype
season Season yes Parent season grouping
dominantCharacteristic string yes Primary characteristic (e.g. "Light", "Warm")
bestColors LAB[] (min 1) yes Core flattering palette
goodColors LAB[] yes Acceptable but non-optimal colors
avoidColors LAB[] yes Colors that clash with or wash out the type
neutrals LAB[] (min 1) yes Recommended neutral palette for staples
metalTones string[] yes Best jewelry/hardware metal tones

1.3 Body Measurement Types#

Body measurements are stored in centimeters. All ten fields are constrained to physiologically plausible maximums (e.g., bust ≤ 300 cm) so that measurement errors from photo analysis are caught at the schema boundary rather than producing absurd downstream recommendations.

BodyMeasurementsSchema (BodyMeasurements) — all values in centimeters, all positive:

Field Constraint Meaning
bust positive, ≤ 300 Full bust circumference at widest point
waist positive, ≤ 300 Natural waist at narrowest point above the navel
hip positive, ≤ 300 Hip circumference at widest point
inseam positive, ≤ 150 Inner leg from crotch to ankle
shoulder positive, ≤ 100 Shoulder width across the back
armLength positive, ≤ 120 Shoulder point to wrist bone
torsoLength positive, ≤ 100 Base of neck to natural waist
thighCircumference positive, ≤ 120 Thigh circumference at widest point
neckCircumference positive, ≤ 80 Neck circumference at the base
wristCircumference positive, ≤ 40 Wrist circumference at narrowest point

BodyShapeSchema (BodyShape) — eight values: Hourglass, Pear, Apple, Rectangle, InvertedTriangle, Oval, Diamond, Athletic. Each enum entry carries a doc comment describing the measurement relationship that defines it.

BodyProportionsSchema (BodyProportions) holds the ratios calculated from raw measurements. These ratios — not the body shape label alone — determine which visual-balance corrections are most appropriate, so two users with the same body shape label but different ratios receive different silhouette guidance.

Field Constraint Meaning
waistToHipRatio positive, ≤ 2 Waist-to-hip ratio (WHR)
shoulderToHipRatio positive, ≤ 3 Upper/lower body balance
bustToWaistRatio positive, ≤ 3 Upper-body definition
torsoToLegRatio positive, ≤ 3 Whether torso or legs are longer
shoulderToWaistRatio positive, ≤ 3 Influences neckline/top recommendations
bodyShape BodyShape Body shape classification from the ratios

SizeRegionSchema (SizeRegion) — US, UK, EU, JP, AU, KR.

ClothingSizeSchema (ClothingSize): region (SizeRegion), category (string), sizeValue (string), optional alphaSize, optional numericSize, optional modifier (Petite | Regular | Tall | Plus).

1.4 Skin Analysis Types#

The skin analysis type system models both the categorical classification of skin (type, tone, concerns) and the quantitative scoring of individual biomarkers. The separation matters: categorical classifications drive routine logic (sensitive skin gets different formulations than oily skin), while biomarker scores enable longitudinal tracking (a user can see their hydration score improving over time).

SkinTypeSchema (SkinType) — Normal, Dry, Oily, Combination, Sensitive.

SkinConcernSchema (SkinConcern) — twelve concerns, each of which maps to specific recommended active ingredients in SKIN_CONCERN_INGREDIENTS: Acne, Wrinkles, DarkSpots, LargePores, Dullness, Redness, Dehydration, Hyperpigmentation, SunDamage, Texture, UndereyeCircles, Sagging.

FitzpatrickScaleSchema (FitzpatrickScale) — TypeI through TypeVI, the Fitzpatrick UV-response phototype scale. Used to determine recommended SPF and burn-time guidance from FITZPATRICK_UV_DATA.

SensitivityLevelSchema (SensitivityLevel) — Mild, Moderate, Severe. Used by IngredientSensitivity to record the severity of a known reaction to a specific ingredient.

SkinAnalysisResultSchema (SkinAnalysisResult) is the output type of a skin analysis run. It carries both the categorical classifications and eleven quantitative biomarker scores, each on a 0–100 scale. Note the direction of scoring: positive-attribute scores (hydration, firmness, clarity) read 100 = best; negative-attribute scores (oiliness, redness) read 0 = none, 100 = severe.

Fields: id (AnalysisId), analyzedAt (datetime), skinType (SkinType), concerns (SkinConcern[]), plus twelve quantitative scores each constrained 0–100: hydration, oiliness, elasticity, pigmentation, texture, wrinkleDepth, poreSize, redness, firmness, clarity, radiance.

SkinToneSchema (SkinTone) — fitzpatrickType (FitzpatrickScale), undertone (SkinUndertone), labColor (LAB), optional hexApproximation.

IngredientSensitivitySchema (IngredientSensitivity) — ingredientName (string), sensitivityLevel (SensitivityLevel), optional notes.

1.5 Hair Analysis Types#

Hair analysis types model the physical properties of hair that determine product and routine compatibility. The Andre Walker curl-pattern system (1A–4C) is the industry standard for curl classification, and porosity is the single most important determinant of whether a product will moisturize or weigh down the hair.

HairTypeSchema (HairType) — the Andre Walker curl-pattern system: Straight1A, Straight1B, Straight1C, Wavy2A, Wavy2B, Wavy2C, Curly3A, Curly3B, Curly3C, Coily4A, Coily4B, Coily4C.

HairDensitySchema (HairDensity) — Fine, Medium, Thick (strand diameter classification).

HairPorositySchema (HairPorosity) — Low, Medium, High. Porosity determines the balance between moisture-rich and protein-rich formulations a hair type needs.

HairConditionSchema (HairCondition) — Healthy, SlightlyDamaged, Damaged, SeverelyDamaged.

HairColorSchema (HairColor) — naturalColor (LAB), currentColor (LAB), isColorTreated (boolean), grayPercentage (0–100), optional naturalLevel (1–10), optional currentLevel (1–10).

HairAnalysisResultSchema (HairAnalysisResult) is the output type of a hair analysis run: id (AnalysisId), analyzedAt, hairType, density, porosity, condition, color (HairColor), plus four 0–100 scores: scalpHealth, moisture, elasticity, shine.

1.6 Fashion Taxonomy Types#

Fashion taxonomy provides the controlled vocabulary that every garment classification and recommendation module uses to describe clothes. Without a shared taxonomy, garment categories and style terms would be ad-hoc strings with no consistent meaning across libraries.

GarmentCategorySchema (GarmentCategory) — twelve top-level categories: Tops, Bottoms, Dresses, Outerwear, Swimwear, Activewear, Sleepwear, Underwear, Accessories, Shoes, Bags, Jewelry.

GarmentSubcategorySchema (GarmentSubcategory) — a flat enum of sub-categories grouped by parent category, including (among others) TShirt/ButtonDown/Blouse/Sweater (Tops), Jeans/Trousers/Skirt (Bottoms), MiniDress/Gown/Jumpsuit (Dresses), Blazer/Coat/Trench (Outerwear), Bikini/OnePiece (Swimwear), Sneakers/Heels/Boots (Shoes), Tote/Crossbody/Clutch (Bags), and Necklace/Ring/Earrings (Jewelry).

FabricTypeSchema (FabricType) — twenty fabric types: Cotton, Silk, Wool, Linen, Polyester, Nylon, Rayon, Cashmere, Denim, Leather, Suede, Satin, Chiffon, Velvet, Tweed, Jersey, Lycra, Organza, Tulle, Lace.

FabricWeightSchema (FabricWeight) — Sheer, Lightweight, Midweight, Heavyweight.

PatternSchema (Pattern) — fourteen patterns: Solid, Stripes, Plaid, Floral, PolkaDots, Geometric, Abstract, Paisley, Houndstooth, Camo, AnimalPrint, Chevron, Gingham, TieDye.

StyleAestheticSchema (StyleAesthetic) — fifteen aesthetics that classify the dominant style identity of a garment or a user's preferences: Classic, Minimalist, Bohemian, Streetwear, Preppy, Romantic, Edgy, Sporty, Glamorous, Vintage, AvantGarde, Scandinavian, Coastal, Western, Gothic.

GarmentConditionSchema (GarmentCondition) — New, Excellent, Good, Fair, Poor.

SeasonSuitabilitySchema (SeasonSuitability) — four boolean flags: spring, summer, autumn, winter.

WardrobeItemSchema (WardrobeItem) is the full wardrobe item entity. It carries all attributes needed to generate outfit recommendations (category, colors, fabric, formality, occasions, seasons) alongside administrative fields for wardrobe management (purchase price, wear count, condition, storage).

Field Type Required Notes
id WardrobeItemId yes UUID v4
profileId PersonalProfileId yes Owning profile
category GarmentCategory yes
subcategory GarmentSubcategory yes
brand string yes
primaryColor LAB yes Primary color in LAB space
accentColors LAB[] default [] Accent/secondary colors
fabric FabricType yes Primary fabric
fabricBlend FabricType[] default [] Additional blend fabrics
fabricWeight FabricWeight yes
pattern Pattern yes
size ClothingSize yes
styleAesthetic StyleAesthetic yes Dominant aesthetic
seasonSuitability SeasonSuitability yes
formality number int 1–10 yes 1 = extremely casual, 10 = black-tie
condition GarmentCondition yes
purchaseDate string datetime optional
purchasePrice number nonnegative optional
currency string length 3 optional ISO 4217
wearsCount number int nonneg. default 0 Total times worn
lastWorn string datetime optional
careInstructions string optional
notes string optional
imageUrl string url optional
tags string[] default []
isAvailable boolean default true Not lent / in repair
createdAt string datetime yes
updatedAt string datetime yes

1.7 Occasion and Context Types#

Occasion and context types capture the circumstances for which an outfit is being recommended. The outfit engine uses all of these fields together: occasion determines formality bounds, dress code refines them, weather context gates fabric and layering choices, and time of day affects color and formality appropriateness.

OccasionTypeSchema (OccasionType) — fifteen occasions: Casual, Business, BusinessCasual, Formal, BlackTie, Cocktail, DateNight, Wedding, Interview, Outdoor, Beach, Festival, Travel, Gym, Lounge.

WeatherContextSchema (WeatherContext) — temperatureMin / temperatureMax (Celsius, −60 to 60), humidity (0–100), precipitation (None | Light Rain | Heavy Rain | Snow | Sleet | Drizzle), uvIndex (0–15), optional windSpeed (km/h, nonnegative), optional description.

DressCodeSchema (DressCode) — refines the formality band within an occasion: WhiteTie, BlackTie, Cocktail, BusinessFormal, BusinessCasual, SmartCasual, Casual, Athleisure, Resort.

TimeOfDaySchema (TimeOfDay) — EarlyMorning, Morning, Afternoon, Evening, Night.

OutfitContextSchema (OutfitContext) — occasion (OccasionType), optional dressCode (DressCode), weather (WeatherContext), optional location, optional setting (Indoor | Outdoor | Both), timeOfDay (TimeOfDay), optional durationHours (positive), optional culturalContext, specialRequirements (string[], default []).

1.8 Recommendation Types#

The recommendation types capture both the output of the outfit engine and the multi-dimensional confidence scores that explain why an outfit was chosen. Exposing confidence as seven distinct scores rather than one overall number lets the user understand the tradeoffs — an outfit may score high on color harmony but low on occasion fit.

RecommendationConfidenceSchema (RecommendationConfidence) — seven scores each constrained 0–1: overall, styleMatch, colorHarmony, occasionFit, trendAlignment, bodyFlattery, weatherAppropriateness.

StylingNoteSchema (StylingNote) — category (Fit | Layering | Accessories | Color | Proportions | Shoes | Hair | Makeup | General), note (string), importance (Essential | Recommended | Optional).

OutfitRecommendationSchema (OutfitRecommendation) is the primary output type of the outfit engine. It includes the wardrobe item IDs that compose the outfit, the full multi-dimensional confidence score, optional swap suggestions for any item in the outfit, and a human-readable rationale explaining the recommendation.

Field Type Required Notes
id RecommendationId yes
profileId PersonalProfileId yes
items WardrobeItemId[] (min 1) yes Wardrobe items composing the outfit
context OutfitContext yes Context the outfit was recommended for
confidence RecommendationConfidence yes Multi-dimensional confidence
stylingNotes StylingNote[] default []
colorHarmonyType ColorHarmony optional Harmony type achieved by the palette
rationale string yes Human-readable reasoning
alternatives array of { replaceItemId, alternativeIds[], reason } default [] Swap suggestions
generatedAt string datetime yes

ShoppingRecommendationSchema (ShoppingRecommendation) — id, profileId, productName, optional brand, category (GarmentCategory), subcategory (GarmentSubcategory), matchReasons (string[], min 1), priceMin / priceMax (nonnegative), currency (length 3), priorityScore (0–1), confidence (RecommendationConfidence), pairsWith (WardrobeItemId[], default []), styleAesthetic, optional suggestedColor (LAB), optional suggestedFabric (FabricType), optional productUrl, optional imageUrl, generatedAt.

1.9 Trend Analysis Types#

Trend types model the lifecycle and origin of fashion trends, enabling the forecasting engine to distinguish between a micro-trend at emergence, a macro-trend at peak, and a classic that has outlasted its original cycle.

TrendStatusSchema (TrendStatus) — Emerging, Growing, Peak, Declining, Classic, Revival.

TrendCategorySchema (TrendCategory) — Color, Silhouette, Pattern, Fabric, Styling, Accessory.

TrendOriginSchema (TrendOrigin) — Runway, Street, Social, Celebrity, Editorial, Subculture.

FashionTrendSchema (FashionTrend) — name, category (TrendCategory), status (TrendStatus), relevanceScore (0–1), seasons (Season[], min 1), emergenceYear (int 1900–2100), origin (TrendOrigin), description, alignedAesthetics (StyleAesthetic[], default []), keyPieces (string[], default []), keyColors (LAB[], default []), predictedLongevity (OneSeasonFad | MultiSeason | YearPlus | EnduringSeveral | PermanentClassic), momentum (Accelerating | Stable | Decelerating), lastUpdated.

1.10 Fragrance Types#

Fragrance types model the olfactory preference profile — preferred families, individual notes, known avoidances, and occasion/season preferences — that the fragrance matching engine uses to recommend perfumes without the user being able to smell them first.

FragranceFamilySchema (FragranceFamily) — twelve families: Floral, Oriental, Woody, Fresh, Citrus, Aromatic, Chypre, Fougere, Gourmand, Aquatic, Green, Musk.

NotePositionSchema (NotePosition) — Top, Middle, Base (fragrance pyramid position; top notes are detected first and fade fastest, base notes linger longest).

FragranceNoteSchema (FragranceNote) — ingredient (string), intensity (NotePosition), description (string).

FragranceProfileSchema (FragranceProfile) — families (FragranceFamily[], min 1), preferredNotes (FragranceNote[], default []), avoidances (array of { ingredient, reason, details? } where reason is Dislike | Allergy | Sensitivity | Migraine | Other), occasionPreferences (array of { occasion, preferredFamilies, preferredIntensity } where preferredIntensity is Light | Moderate | Strong | Statement), optional preferredConcentration (EauFraiche | EauDeCologne | EauDeToilette | EauDeParfum | Parfum), seasonalPreferences (array of { season, preferredFamilies }).

1.11 Composite Profile Type#

PersonalStyleProfileSchema (PersonalStyleProfile) is the root entity of the domain — the aggregate that recommendation modules read from. It brings together the outputs of every analysis engine into a single object. All analysis fields are optional because the profile can be partially complete; the profileCompleteness score (computed by @aglaea/unified-profile) tracks which analyses are present.

Field Type Required Meaning
id PersonalProfileId yes
displayName string yes
seasonalPalette SeasonalColorPalette optional Seasonal color analysis result
skinTone SkinTone optional
bodyMeasurements BodyMeasurements optional
bodyProportions BodyProportions optional Calculated proportions
skinAnalysis SkinAnalysisResult optional Latest skin analysis
ingredientSensitivities IngredientSensitivity[] default []
hairAnalysis HairAnalysisResult optional Latest hair analysis
styleAesthetics StyleAesthetic[] default [] Ranked preferred aesthetics
sizes ClothingSize[] default [] Preferred sizes by region
fragranceProfile FragranceProfile optional
createdAt string datetime yes
updatedAt string datetime yes

2. Core Domain Constants (@aglaea/core)#

constants.ts provides reference data tables consumed by analysis and recommendation modules. These are read-only lookup tables — they encode domain knowledge (what SPF does Fitzpatrick Type III require? what ratio thresholds classify a body as pear-shaped?) that would otherwise be hardcoded in individual libraries. Centralizing them here ensures consistency and allows them to be updated in one place.

  • Size conversion chartsWOMENS_SIZE_CHART, MENS_SIZE_CHART, WOMENS_SHOE_CHART, MENS_SHOE_CHART (US/UK/EU mappings), ALPHA_TO_US_WOMENS, ALPHA_TO_US_MENS (alpha-to-numeric maps).
  • Measurement-to-size rangesBUST_TO_US_SIZE, WAIST_TO_US_SIZE, HIP_TO_US_SIZE (cm ranges mapped to US women's sizes).
  • Color theory constantsCOLOR_HARMONY_ANGLES (HSL wheel offsets per harmony type), CIE_D65 / CIE_D50 / CIE_A (illuminant white points), SRGB_TO_XYZ_MATRIX, XYZ_TO_SRGB_MATRIX, LAB_EPSILON (0.008856), LAB_KAPPA (903.3).
  • FITZPATRICK_UV_DATA — per-phototype UV reaction data: minimum erythema dose range, burn-time range, recommended SPF, UV response description, melanin index range.
  • FABRIC_CARE_INSTRUCTIONS — per-fabric care set: wash, dry, iron, notes, maxWashTemp, dryerSafe, bleachSafe.
  • BODY_SHAPE_THRESHOLDS — ratio thresholds for body-shape classification (hourglass, pear, apple, rectangle, invertedTriangle, athletic, diamond, oval).
  • IDEAL_PROPORTIONS — reference proportion ratios (golden waist-to-hip, balanced shoulder-to-hip, fashion-figure head ratio, torso-to-leg ratio).
  • SEASONAL_PALETTE_ANCHORS — per-SeasonalSubtype anchor data: parent season, dominant characteristic, anchor bestColors/neutrals/avoidColors in LAB, and metalTones.
  • SUBCATEGORY_FORMALITY — default formality score (1–10) per garment subcategory.
  • SUBCATEGORY_TO_CATEGORY — maps each subcategory to its parent category.
  • LAYERING_ORDER — stacking order (0 = innermost) per garment category.
  • FRAGRANCE_NOTE_TIMING — top/middle/base note onset, peak, fade, and duration (minutes); FRAGRANCE_CONCENTRATION_LONGEVITY — longevity hours and oil-percentage ranges per concentration tier.
  • PATTERN_COMPATIBILITY — per-pattern set of mix-compatible patterns.
  • FABRIC_SEASONAL_SCORES — fabric suitability score (0–1) per season.
  • SKIN_CONCERN_INGREDIENTS — per-SkinConcern recommended ingredient list with a description.

3. Configuration (@aglaea/core)#

config.ts defines AglaeaConfigSchema (AglaeaConfig), a section-oriented, Zod-validated configuration object. Every section has defaults, so {} parses to a valid config — libraries never have to handle a missing config section. Config values can be overridden at startup via direct object overrides or via environment variables, following the AGLAEA_<SECTION>_<KEY> naming convention (e.g., AGLAEA_COLOR_ANALYSIS_ENABLED=false).

The configuration sections and their key fields are:

Section Schema Key fields (with defaults)
colorAnalysis ColorAnalysisConfigSchema enabled (true), defaultIlluminant (D65), ciede2000Threshold (2.0), seasonalAnalysisVersion (1)
skinAnalysis SkinAnalysisConfigSchema enabled (true), minConfidenceScore (0.7), biomarkerCount (12), fitzpatrickAccuracy (0.95)
hairAnalysis HairAnalysisConfigSchema enabled (true), walkerClassificationVersion (2)
bodyAnalysis BodyAnalysisConfigSchema enabled (true), sizeConversionRegions (['US','UK','EU'])
recommendations RecommendationsConfigSchema enabled (true), maxResults (20), minConfidenceThreshold (0.5), enableAIEnhancement (false), trendWeight (0.3), personalStyleWeight (0.5)
trends TrendsConfigSchema enabled (true), forecastHorizonDays (90), minDataPointsForPrediction (30), adoptionCurveModel (rogers)
fragrance FragranceConfigSchema enabled (true), maxRecommendations (10), seasonalBonus (0.15)
cache CacheConfigSchema defaultTTLMs (300000), skinAnalysisTTLMs (1800000), trendDataTTLMs (300000), colorPaletteTTLMs (3600000)
rateLimit RateLimitConfigSchema enabled (true), defaultWindowMs (60000), defaultMaxRequests (100)

Loading and accessors. loadAglaeaConfig(overrides?) merges, in priority order: schema defaults, caller-supplied overrides, and environment-variable overrides. Environment variables use a flat AGLAEA_<SECTION>_<KEY> format (example: AGLAEA_COLOR_ANALYSIS_ENABLED=false{ colorAnalysis: { enabled: false } }). validateAglaeaConfig(config) returns a safeParse-style result. getConfigSection(config, section) is a type-safe section accessor. mergeConfigs(base, override) deep-merges two partials (arrays replace, not concatenate). ConfigManager is a stateful container with getAll/get/set/reset and change-subscription support.


4. AI Orchestration Types (@aglaea/ai-orchestrator)#

libs/aglaea/ai-orchestrator/src/types.ts defines the contracts that every library uses when requesting ML inference. The library ships orchestrator, model-registry, ab-testing, fallback, inference-queue, batch-inference, monitoring, cost-tracker, warmup, and edge-deployment modules — the types below are shared across all of them.

Branded type. ModelId (Brand<string, 'ModelId'>), constructed via modelId(raw).

ModelProvider (enum) — the set of supported ML inference providers: OpenAI, Anthropic, HuggingFace, Custom, RunPod, Replicate, Local.

ModelCapability (enum) — the ten capabilities a model can be registered for: SkinAnalysis, HairAnalysis, BodyAnalysis, ColorAnalysis, OutfitRecommendation, TrendForecasting, FragranceMatching, VirtualTryOn, FabricDetection, StyleClassification.

ModelConfig — the full descriptor of a registered model: id (ModelId), name, provider (ModelProvider), endpoint, optional apiKey (in-memory only, never persisted), capabilities (ModelCapability[]), version, maxBatchSize, timeoutMs, costPerInference (USD), isActive, warmupRequired, optional metadata.

InferencePrioritylow | normal | high | critical. The helper priorityWeight(p) maps these to numeric weights (critical 4 → low 1) for the priority queue.

InferenceRequest<T>id, modelId, input, priority, timestamp, optional metadata. InferenceResult<T>requestId, modelId, output, latencyMs, cost, cached, modelVersion, timestamp. InferenceErrorrequestId, modelId, error, code, retryable.

ABTestConfigid, name, controlModelId, treatmentModelId, trafficSplitPercent (0–100), startDate, optional endDate, capability, isActive. ABTestResulttestId, controlMetrics, treatmentMetrics, optional winner (control | treatment), confidence.

ModelMetrics — per-model performance tracking: totalRequests, successRate, avgLatencyMs, p95LatencyMs, p99LatencyMs, avgCost, totalCost, errorRate.

QueuedInference — wraps a request with its resolve/reject callbacks and enqueuedAt. QueueStatsprocessed, failed, queued, avgWaitMs.

Edge deployment. TargetDevice (cpu | gpu | tpu | npu), Quantization (none | int8 | int4 | fp16), EdgeDeploymentConfig (modelId, targetDevice, quantization, maxMemoryMb, batchSize, warmupSamples).

Warm-up. WarmupResult (modelId, success, latencyMs, optional error), WarmupStatus (cold | warming | warm | failed).


5. REST API Surface (@aglaea/api-services)#

@aglaea/api-services defines the REST API as typed RouteDefinition objects grouped by domain module, aggregated by api-registry.ts. The registry constant API_VERSION is v1 and BASE_PATH is /api/v1. All endpoint paths use colon-prefixed path parameters (e.g. :profileId).

A RouteDefinition carries method, path, summary, tags, optional requestBody (a SchemaRef with description, contentType, schema), optional queryParams / pathParams (maps of ParamDef), a responses map (HTTP status → ResponseDef), an auth field (required | optional | none), and an optional rateLimit ({ windowMs, max }).

The registry aggregates 64 endpoints across seven modules. All endpoints require authentication (auth: 'required') except the eight Trends/Discovery endpoints noted below.

5.1 Profile Endpoints (profile-endpoints.ts)#

These ten endpoints cover the full lifecycle of a personal style profile — creation, retrieval, update, deletion, photo upload, preference management, history browsing, and external sync.

Method Path Purpose Auth
GET /api/v1/profiles/:profileId Get personal profile by ID req.
POST /api/v1/profiles Create a new personal profile req.
PUT /api/v1/profiles/:profileId Update an existing profile req.
DELETE /api/v1/profiles/:profileId Delete a profile and all associated data req.
GET /api/v1/profiles/:profileId/summary Get condensed profile summary with key metrics req.
POST /api/v1/profiles/:profileId/photo Upload or replace the profile photo req.
GET /api/v1/profiles/:profileId/preferences Get style/notification/privacy preferences req.
PUT /api/v1/profiles/:profileId/preferences Update user preferences req.
GET /api/v1/profiles/:profileId/history Get paginated activity history req.
POST /api/v1/profiles/:profileId/sync Trigger a full sync from external sources req.

5.2 Analysis Endpoints (analysis-endpoints.ts)#

These ten endpoints submit photos or measurements for analysis and retrieve results. The six analysis-submission endpoints (POST /analysis/{type}) accept multipart/form-data and respond 202 with an AnalysisJob schema — analysis is asynchronous. They enforce per-minute rate limits (15/min for skin/color/face/hair/nails, 10/min for body).

Method Path Purpose Auth
POST /api/v1/analysis/skin Run a comprehensive skin analysis req.
POST /api/v1/analysis/color Run seasonal and undertone color analysis req.
POST /api/v1/analysis/face-shape Run face shape detection and proportion analysis req.
POST /api/v1/analysis/body Run body shape and proportion analysis req.
POST /api/v1/analysis/hair Run hair type, texture, and condition analysis req.
POST /api/v1/analysis/nails Run nail shape, health, and color analysis req.
GET /api/v1/analysis/:analysisId Retrieve a completed analysis result by ID req.
GET /api/v1/analysis/history/:profileId Get paginated analysis history (filterable by type) req.
POST /api/v1/analysis/compare Compare two analyses (before/after) to track progress req.
DELETE /api/v1/analysis/:analysisId Delete an analysis result and its images req.

5.3 Recommendation Endpoints (recommendation-endpoints.ts)#

These ten endpoints generate personalized recommendations across the platform's major recommendation types — outfit, shopping, style tips, color palette, skincare routine, hair care, and makeup. All are POST requests because they consume context (occasion, weather, skin analysis ID) from the request body.

Method Path Purpose Auth
POST /api/v1/recommendations/outfit Generate outfit recommendations for an occasion req.
POST /api/v1/recommendations/shopping Get shopping recommendations to fill wardrobe gaps req.
POST /api/v1/recommendations/style-tips Get personalized style tips req.
POST /api/v1/recommendations/color-palette Generate a personalized color palette req.
POST /api/v1/recommendations/skincare-routine Generate a skincare routine from skin analysis req.
POST /api/v1/recommendations/hair-care Generate a hair care routine from hair analysis req.
POST /api/v1/recommendations/makeup-look Generate a makeup look from face shape and coloring req.
GET /api/v1/recommendations/:recId Get detailed recommendation by ID req.
POST /api/v1/recommendations/:recId/feedback Submit feedback on a recommendation req.
GET /api/v1/recommendations/history/:profileId Get paginated recommendation history req.

5.4 Wardrobe Endpoints (wardrobe-endpoints.ts)#

These ten endpoints manage the digital wardrobe — adding, updating, and removing items, logging wear events, retrieving analytics, identifying gaps, and generating a capsule wardrobe from existing inventory.

Method Path Purpose Auth
GET /api/v1/wardrobe/:profileId Get the full wardrobe inventory req.
POST /api/v1/wardrobe/:profileId/items Add a new item to the wardrobe req.
PUT /api/v1/wardrobe/:profileId/items/:itemId Update an existing wardrobe item req.
DELETE /api/v1/wardrobe/:profileId/items/:itemId Remove an item from the wardrobe req.
POST /api/v1/wardrobe/:profileId/items/:itemId/wear Log that an item was worn on a date req.
GET /api/v1/wardrobe/:profileId/analytics Get analytics including cost-per-wear req.
GET /api/v1/wardrobe/:profileId/gaps Identify wardrobe gaps req.
POST /api/v1/wardrobe/:profileId/capsule Generate a capsule wardrobe from existing items req.
GET /api/v1/wardrobe/:profileId/outfits Get outfit history with wear dates and ratings req.
POST /api/v1/wardrobe/:profileId/digitize Digitize a clothing item from a photo (AI) req.

5.5 Virtual Try-On Endpoints (tryon-endpoints.ts)#

These eight endpoints submit try-on requests for different item types and retrieve results. Try-on sessions are persistent — a session ID is returned immediately, and the rendered result is retrieved asynchronously.

Method Path Purpose Auth
POST /api/v1/tryon/fashion Virtually try on a clothing item (body-mapped) req.
POST /api/v1/tryon/makeup Virtually try on a makeup look (face-mapped AR) req.
POST /api/v1/tryon/hair Virtually try on a hairstyle or hair color req.
POST /api/v1/tryon/nails Virtually try on a nail design or color req.
POST /api/v1/tryon/accessories Virtually try on glasses, jewelry, or hats req.
POST /api/v1/tryon/avatar Generate a 3D avatar from profile data and photos req.
GET /api/v1/tryon/:sessionId Get the result of a try-on session req.
DELETE /api/v1/tryon/:sessionId Delete a try-on session and its rendered assets req.

5.6 Conversation Endpoints (conversation-endpoints.ts)#

These eight endpoints drive multi-turn dialogue with the AI style assistant. Sessions are stateful — each message is sent to an existing session so the assistant can maintain context across turns.

Method Path Purpose Auth
POST /api/v1/conversations Start a conversation with the AI style assistant req.
POST /api/v1/conversations/:sessionId/message Send a message and receive a response req.
GET /api/v1/conversations/:sessionId Retrieve the full message history req.
DELETE /api/v1/conversations/:sessionId End and archive a conversation session req.
GET /api/v1/conversations/:sessionId/suggestions Get contextual follow-up suggestions req.
POST /api/v1/conversations/:sessionId/feedback Rate a specific assistant response req.
GET /api/v1/conversations/active List all active conversations for the user req.
POST /api/v1/conversations/:sessionId/context Update the conversation context req.

These eight endpoints are the only ones in the registry that do not require authentication for all callers — trend and discovery data can be surfaced to anonymous users for browsing. Personalized endpoints (/personalized/:profileId and /forecast) require authentication because they depend on profile data.

Method Path Purpose Auth
GET /api/v1/trends Get current trending styles, colors, silhouettes optional
GET /api/v1/trends/:trendId Get detailed information about a trend optional
GET /api/v1/trends/personalized/:profileId Get trends personalized to a profile required
GET /api/v1/trends/forecast Get trend forecasts for upcoming seasons required
GET /api/v1/discovery/inspiration Get a curated inspiration feed optional
GET /api/v1/discovery/celebrities/:celebId Get style profile and looks for a celebrity optional
GET /api/v1/discovery/communities List style communities and interest groups optional
POST /api/v1/discovery/search Search across trends, looks, products, communities optional

6. Domain Event System (@aglaea/events)#

@aglaea/events provides the typed domain event system that decouples Aglaea's modules. When an analysis completes, it publishes a typed event; the skincare-routine library subscribes to that event and updates its recommendations without the analysis library needing to know it exists. This decoupling is what allows 93 libraries to coordinate without forming a tightly coupled dependency web.

The library ships publisher, consumer, dead-letter, replay, analytics, and helpers modules over the core types below.

6.1 Core Event Types#

These types form the envelope that wraps every domain event, regardless of payload type.

  • DomainEvent<T>id (UUID v4), type (dot-namespaced), timestamp (ISO-8601), version (schema version number), source (originating context), optional correlationId, optional causationId, optional metadata, payload (typed T).
  • EventEnvelope<T> — wraps a DomainEvent<T> with routingKey, optional partition, optional deduplicationId.
  • EventHandler<T>(event: DomainEvent<T>) => void | Promise<void>.
  • EventFilter — optional source, correlationId, metadata predicate.
  • EventSubscriptionid, eventType, handler, optional filter.
  • EventPublisherOptions — optional retries, timeout.
  • DeadLetterEntry<T>event, error, attemptCount, lastAttempt, optional nextRetry.
  • ReplayFilter — optional fromTimestamp, toTimestamp, eventTypes, source, correlationId, limit, offset.

6.2 Event Type Constants (AGLAEA_EVENT_TYPES)#

The AGLAEA_EVENT_TYPES const object defines 23 event type strings grouped by domain area. AglaeaEventType is the TypeScript union of all values, which means any switch statement on an event type will produce a compile error if a case is missed.

Constant Type string Payload interface
SKIN_ANALYSIS_COMPLETED aglaea.analysis.skin-completed SkinAnalysisCompletedPayload
BODY_ANALYSIS_COMPLETED aglaea.analysis.body-completed BodyAnalysisCompletedPayload
HAIR_ANALYSIS_COMPLETED aglaea.analysis.hair-completed HairAnalysisCompletedPayload
COLOR_ANALYSIS_COMPLETED aglaea.analysis.color-completed ColorAnalysisCompletedPayload
ANALYSIS_FAILED aglaea.analysis.failed AnalysisFailedPayload
OUTFIT_RECOMMENDED aglaea.recommendation.outfit-recommended OutfitRecommendedPayload
SHOPPING_RECOMMENDED aglaea.recommendation.shopping-recommended ShoppingRecommendedPayload
STYLE_TIP_GENERATED aglaea.recommendation.style-tip-generated StyleTipGeneratedPayload
RECOMMENDATION_ACCEPTED aglaea.recommendation.accepted RecommendationAcceptedPayload
RECOMMENDATION_REJECTED aglaea.recommendation.rejected RecommendationRejectedPayload
WARDROBE_ITEM_ADDED aglaea.wardrobe.item-added WardrobeItemAddedPayload
WARDROBE_ITEM_REMOVED aglaea.wardrobe.item-removed WardrobeItemRemovedPayload
WARDROBE_ITEM_WORN aglaea.wardrobe.item-worn WardrobeItemWornPayload
WARDROBE_ITEM_UPDATED aglaea.wardrobe.item-updated WardrobeItemUpdatedPayload
OUTFIT_CREATED aglaea.wardrobe.outfit-created OutfitCreatedPayload
OUTFIT_RATED aglaea.wardrobe.outfit-rated OutfitRatedPayload
PURCHASE_COMPLETED aglaea.purchase.completed PurchaseCompletedPayload
WISHLIST_ADDED aglaea.purchase.wishlist-added WishlistAddedPayload
CART_ABANDONED aglaea.purchase.cart-abandoned CartAbandonedPayload
RETURN_INITIATED aglaea.purchase.return-initiated ReturnInitiatedPayload
PROFILE_FOLLOWED aglaea.social.profile-followed ProfileFollowedPayload
OUTFIT_SHARED aglaea.social.outfit-shared OutfitSharedPayload
STYLE_BOARD_CREATED aglaea.social.style-board-created StyleBoardCreatedPayload
STYLE_BOARD_LIKED aglaea.social.style-board-liked StyleBoardLikedPayload

6.3 Event Payloads#

The following payload shapes illustrate the data carried by the most commonly consumed events. All payload types are defined in events.ts and are exported alongside their event constants.

  • SkinAnalysisCompletedPayloadprofileId, analysisId, skinType (oily | dry | combination | normal | sensitive), fitzpatrickType (1–6), overallScore, concerns (SkinConcern[] where each is { name, severity: 'low' | 'moderate' | 'high' }), timestamp.
  • BodyAnalysisCompletedPayloadprofileId, analysisId, bodyShape (hourglass | pear | apple | rectangle | inverted-triangle), measurements (MeasurementsSummary: optional bust, waist, hips, height, weight, inseam).
  • HairAnalysisCompletedPayloadprofileId, analysisId, hairType (1a4c), healthScore.
  • ColorAnalysisCompletedPayloadprofileId, analysisId, seasonalSubtype (12-value kebab-case union), undertone (warm | cool | neutral).
  • OutfitRecommendedPayloadprofileId, recommendationId, itemIds, confidenceScore, occasion.
  • WardrobeItemAddedPayloadprofileId, itemId, category, brand.
  • PurchaseCompletedPayloadprofileId, productId, price, retailer, category.

7. API-Services Event Catalog (@aglaea/api-services)#

Separately from @aglaea/events, @aglaea/api-services declares 39 EventDefinition records intended for documentation and contract generation, aggregated by api-registry.ts. These records describe the same domain events from the perspective of the API contract surface — each EventDefinition carries type (dot identifier), description, payload (schema name), topic (message-bus topic), and version. They use a different naming scheme from the @aglaea/events constants and are not the runtime event type strings.

Module file Count Topics
analysis-events.ts 10 analysis.skin, analysis.color, analysis.face, analysis.body, analysis.hair, analysis.nails, analysis.progress, analysis.batch, analysis.profile
recommendation-events.ts 10 recommendations.{outfit,shopping,routine,feedback,lifecycle,trends,tips,batch}
wardrobe-events.ts 10 wardrobe.{items,wear,outfits,analytics,capsule}
social-events.ts 10 social.{outfits,communities,challenges,achievements,experts,feed}

Representative event types from the catalog: skin.analysis.completed, color.analysis.completed, outfit.recommended, routine.recommended, trend.alert.generated, wardrobe.item.added, wardrobe.gap.detected, wardrobe.capsule.generated, outfit.shared, community.joined, challenge.completed, achievement.unlocked, badge.earned.


8. Persistence Schemas (@aglaea/database)#

@aglaea/database defines the persistence layer. It uses Knex for SQL migrations and Zod schemas for table row validation. There is no Prisma in this domain — the direct Knex + Zod pattern was chosen to keep the persistence layer free of ORM magic and to share the same Zod validation approach as the rest of @aglaea/core. The target store is PostgreSQL. Dependencies are minimal: knex, zod, and uuid.

8.1 Migrations#

Migrations are Knex up/down functions, re-exported from migrations/index.ts. They run in sequence; each migration builds on the previous one.

  1. 20260318000001_initial_setup — creates the uuid-ossp and pg_trgm PostgreSQL extensions, the custom enum types (e.g. seasonal_subtype, skin_undertone, color_temperature, gender_type), and the shared updated_at trigger function.
  2. 20260318000002_core_tables — core domain tables (profiles, analysis records, wardrobe, outfits, recommendations).
  3. 20260318000003_catalog_tables — product and catalog tables (products, trends, ingredients, fabrics, brands, retailers).
  4. 20260318000004_social_audit — social and audit tables (follows, shares, style boards, audit log).
  5. 20260318000005_seed_data — reference data seeding.

8.2 Schema Modules#

The schema/index.ts barrel re-exports sixteen schema modules. Each module exports a full record schema plus CreateInput and (for mutable entities) UpdateInput variants derived via .omit() / .partial():

common, profiles, skin-analysis, body-measurements, wardrobe, outfits, products, recommendations, preferences, feedback, trends, ingredients, fabrics, brands, social, audit.

common.ts provides shared building blocks used by all other modules: UuidSchema, TimestampSchema, HexColorSchema, UrlSchema, CurrencyCodeSchema, PaginationSchema, SortDirectionSchema, SortSchema, DateRangeFilterSchema, NumericRangeFilterSchema, JsonValueSchema, JsonObjectSchema, StringArrayJsonSchema.

8.3 PersonalProfile (profiles.ts)#

PersonalProfileSchema is the database-layer representation of a user's profile. It carries less data than PersonalStyleProfile from @aglaea/core because analysis results are stored in their own tables and joined when needed, rather than embedded in the profile row.

PersonalProfileSchemaid (UUID), userId (UUID, FK to auth system), displayName, email, optional dateOfBirth (YYYY-MM-DD), optional gender (GenderSchema: female | male | non_binary | prefer_not_to_say | other), optional location (LocationSchema: city, country ISO 3166-1 alpha-2, timezone IANA), optional profileImageUrl, optional seasonalSubtype (SeasonalSubtypeDbSchema, 12-value), optional skinUndertone (Cool | Warm | Neutral | Olive), optional colorTemperature (Cool | Warm | Neutral), createdAt, updatedAt.

8.4 SkinAnalysisRecord (skin-analysis.ts)#

Each analysis run produces a dated history row, not an overwrite, so the full history of a user's skin condition is reconstructable over time. The eleven dimension scores here correspond exactly to those in SkinAnalysisResultSchema from @aglaea/core.

SkinAnalysisRecordSchemaid, profileId (FK), analysisDate, skinType (SkinTypeDbSchema), optional fitzpatrickType, optional undertone, eleven 0–100 dimension scores (hydrationScore, oilinessScore, elasticityScore, pigmentationScore, textureScore, wrinkleDepthScore, poreSizeScore, rednessScore, firmnessScore, clarityScore, radianceScore) plus a computed overallScore, concerns (SkinConcernDb[], default []), recommendations (string[], default []), optional imageUrl, optional metadata (JSON), createdAt. The module also exports IngredientSensitivityRecordSchema.

8.5 BodyMeasurementRecord (body-measurements.ts)#

Like skin analysis, body measurements are stored as dated history rows. All measurement fields are optional because not every photo submission produces all ten measurements.

BodyMeasurementRecordSchemaid, profileId (FK), measurementDate, ten optional cm circumference/length fields (bustCm, waistCm, hipCm, inseamCm, shoulderWidthCm, armLengthCm, torsoLengthCm, thighCircumferenceCm, neckCircumferenceCm, wristCircumferenceCm), optional heightCm and weightKg, optional bodyShape (BodyShapeDbSchema: Hourglass, Pear, Apple, Rectangle, InvertedTriangle, Oval, Diamond, Athletic), optional bodyProportions (JSON), optional clothingSizes (JSON), optional notes, optional measuredBy (MeasuredBySchema), createdAt, updatedAt.

8.6 WardrobeItemDb (wardrobe.ts)#

The wardrobe item database schema. Note that colors are stored as hex strings (for display) rather than LAB (for computation), since LAB conversion is applied in the application layer when the item is loaded for recommendation processing.

WardrobeItemDbSchemaid, profileId (FK to personal_profiles), category (GarmentCategoryDbSchema), optional subcategory (free-text), optional brand, name, optional description, optional primaryColorHex / accentColorHex (HexColorSchema), optional fabricType (FabricTypeDbSchema), optional fabricBlend (free-text), optional pattern (PatternDbSchema), optional styleAesthetic (StyleAestheticDbSchema), seasonSuitability (string-array JSON, default []), optional formalityLevel (1–10), optional condition (GarmentConditionDbSchema), optional purchaseDate / purchasePrice / purchaseCurrency / retailer, optional size / sizeRegion, wearCount (default 0), optional lastWornDate, optional careInstructions, imageUrls (JSON array, default []), tags (JSON array, default []), isFavorite (default false), isArchived (default false), createdAt, updatedAt.

8.7 Outfit (outfits.ts)#

OutfitSchemaid, profileId (FK), name, optional description, items (string-array JSON of wardrobe item UUIDs, default []), optional occasion, optional dressCode, optional weatherContext (JSON), optional dateWorn, optional rating (1–5), optional notes, optional imageUrl, isPublic (default false), createdAt, updatedAt. The module also exports OutfitItemSchema.

8.8 RecommendationRecord (recommendations.ts)#

Recommendation records persist the full multi-dimensional confidence scores and feedback, enabling the preference learning pipeline to train on both the recommendation and its outcome.

RecommendationRecordSchemaid, profileId (FK), type (RecommendationTypeDbSchema: outfit | shopping | style_tip | color_palette), optional context (JSON), items (array of JSON objects, default []), seven optional 0–1 confidence scores (confidenceScore, styleMatchScore, colorHarmonyScore, occasionFitScore, trendAlignmentScore, bodyFlatteryScore, weatherScore), stylingNotes (array of JSON objects, default []), optional wasAccepted, optional feedbackRating (1–5), optional feedbackText, createdAt.

8.9 Product (products.ts)#

Products in the Aglaea database represent catalog items from retail partners, normalized into the domain's type system for matching against profile attributes.

ProductSchemaid, optional externalId (retailer sync key), name, optional brand, optional description, optional category / subcategory, optional price / priceCurrency, optional retailerUrl, imageUrls (JSON array), colors (JSON array), optional fabricType, optional pattern, optional styleAesthetic, sizes (JSON array), seasonSuitability (JSON array), optional formalityLevel (1–10), optional rating (0–5), optional reviewCount, isAvailable (default true), optional lastSyncedAt, timestamps.

8.10 Trend (trends.ts)#

TrendSchema plus its database-layer enums. Note that the database enums for trend category, status, and origin use more granular values than the @aglaea/core types, providing richer data for the trend forecasting engine.

  • TrendCategoryDbSchemacolor, fabric, pattern, silhouette, style, accessory, footwear, beauty, lifestyle (nine values, vs. six in core).
  • TrendStatusDbSchemaemerging, rising, peak, declining, fading, classic, revived (seven values, vs. six in core).
  • TrendOriginDbSchemarunway, street, celebrity, social_media, subculture, designer, vintage_revival, technology, sustainability (nine values, vs. six in core).

8.11 Other Schema Modules#

These modules cover user preferences, feedback, reference data (ingredients, fabrics, brands), social interactions, and audit logging.

  • preferences.tsUserPreferencesSchema plus SustainabilityPreferenceSchema, SizePreferenceSchema, CoveragePreferenceSchema, FragranceConcentrationSchema.
  • feedback.tsFeedbackSchema, FeedbackTargetTypeSchema.
  • ingredients.tsIngredientSchema, IngredientCategoryDbSchema.
  • fabrics.tsFabricMaterialSchema, FabricCategoryDbSchema, PriceRangeDbSchema.
  • brands.tsBrandSchema and RetailerSchema, BrandPriceRangeDbSchema.
  • social.tsFollowSchema, ShareSchema, StyleBoardSchema, ShareTargetTypeSchema, SharePlatformSchema.
  • audit.tsAuditLogSchema, AuditActionSchema.

9. SDK Surface (@aglaea/sdk)#

@aglaea/sdk provides a high-level TypeScript client for consuming the @aglaea/api-services endpoints. It handles authentication, retry logic, and file uploads, so callers interact with typed domain methods rather than raw HTTP requests.

AglaeaClient is the primary entry point, composed of five sub-components also exported as instance fields:

  • http (AglaeaHttpClient) — the underlying HTTP client
  • interceptors (InterceptorManager) — request/response interceptor chain
  • retry (RetryHandler) — exponential back-off with maxRetries defaulting to 3 and baseDelayMs to 1000
  • batch (BatchProcessor) — batch multiple requests together
  • uploader (FileUploader) — handles multipart file uploads for analysis and photo endpoints

The client is constructed from an AglaeaSDKConfig. Its domain methods wrap REST endpoints through the retry handler:

Method HTTP call
analyzeSkin(profileId, imageUrl) POST /api/v1/analysis/skin
analyzeBody(profileId, measurements) POST /api/v1/analysis/body
getColorPalette(profileId) GET /api/v1/profiles/:profileId/colors
getOutfitRecommendation(profileId, context) POST /api/v1/recommendations/outfit
getShoppingRecommendations(...) GET /api/v1/recommendations/shopping
getTrends(category?, limit?) GET /api/v1/trends
getWardrobeItems(profileId) GET /api/v1/profiles/:profileId/wardrobe
addWardrobeItem(profileId, item) POST /api/v1/profiles/:profileId/wardrobe
uploadImage(profileId, file) (file upload via FileUploader)
destroy() Releases client resources

The SDK module set also includes auth, websocket, and http-client. The SDK uses its own client-facing result types (APIResponse<T>, SkinAnalysisResult, BodyAnalysisResult, ColorPalette, OutfitRecommendation, WardrobeItem, TrendsResponse, ShoppingRecommendationsResponse, UploadResult, etc.) defined in sdk/src/types.ts.


10. Technology Stack#

The technology choices below apply across all 93 Aglaea libraries. Each library declares its own package.json, exposing source directly via "main": "./src/index.ts" — there is no compiled output checked in, and libraries depend on each other via TypeScript path aliases resolved at build time.

Layer Technology / Library
Language TypeScript (Node.js, ESM — every package is "type": "module")
Validation Zod (every @aglaea/core and @aglaea/database schema)
Persistence PostgreSQL — Knex for migrations, Zod schemas for row validation
Database extns. uuid-ossp, pg_trgm
Dependency mgmt. pnpm catalog (catalog: refs)
Testing Vitest (*.test.ts / *.spec.ts co-located per library)
Build executor @nx/js:tsc
Test executor @nx/vite:test

Dependencies are kept minimal by design: @aglaea/core depends only on zod; @aglaea/database on knex, zod, uuid. This keeps the foundation layer importable without pulling in unnecessary transitive dependencies.


Grounding#

Every type, enum value, endpoint path, event constant, schema field, and configuration default in this document was read directly from source under libs/aglaea/ — primarily core/src/types.ts, core/src/constants.ts, core/src/config.ts, ai-orchestrator/src/types.ts, events/src/types.ts, events/src/events.ts, api-services/src/*.ts, database/src/schema/*.ts, database/src/migrations/*.ts, and sdk/src/client.ts. Counts (93 libraries, 64 endpoints, 23 event constants, 39 EventDefinition records, 16 schema modules) reflect the current monorepo state. Aglaea is a pure library domain; no apps/aglaea/ or services/aglaea/ exists.