Named after Asase Yaa, the Akan earth goddess of fertility and sustenance. Asase is the food and agriculture operations intelligence domain for Ghana's complete food value chain, covering 19 business units from farm production through processing, cold chain, logistics, quality assurance, export, and market operations.
This document is the authoritative technical reference for everything
implemented in the libs/asase/* libraries and apps/asase/* applications.
Every entity, enum, function, table, and constant below is traceable to source
code in the repository.
The specification is organised from the foundational core outward: §1 gives the top-level domain metrics, §2 lists all libraries, §3–§14 cover the core type system in depth (branded IDs, enums, value objects, domain entities, services, validation, utilities, errors, and constants), §15 documents the database schema (36 tables, 27 PostgreSQL enum types), §16 covers infrastructure services, §17 catalogues the public API surface of each specialised library, and §18–§21 cover applications, configuration, cross- domain integration, and external data sources.
Use features.md for narrative explanations of what each library does and why.
Use this document to look up exact type signatures, enum values, function names,
and schema details.
1. Domain Overview#
The table below summarises the domain's key properties. These counts are anchored to the source — if you add a library or table, update these values to keep the document coherent.
| Property | Value |
|---|---|
| Domain name | asase |
| Scope | Ghana food and agriculture operations intelligence |
| Library count | 15 (libs/asase/*) |
| Application count | 5 (apps/asase/*) |
| Business units | 19 |
| Database | PostgreSQL (Drizzle ORM, 36 tables in @asase/core, pgvector) |
| Language | TypeScript (ESM) |
| Validation | Zod (@asase/core, @asase/infrastructure); plus hand-written ValidationResult validators |
| Testing | Vitest |
| Build | @nx/js:tsc |
| Geographic focus | Ghana (16 administrative regions, 5 agro-ecological zones) |
| Project tags | ["scope:asase", "layer:domain", "type:lib"] |
All library package.json files use "name": "@asase/<lib>",
"version": "0.1.0", "type": "module". Most libraries depend on @asase/core
via workspace:*. @asase/financials, @asase/connectors, and @asase/sota
have no @asase/core dependency.
2. Library Inventory#
All 15 domain libraries and the migration package are implemented. Three
libraries (@asase/financials, @asase/connectors, @asase/sota) have no
@asase/core dependency; all others depend on @asase/core via workspace:*.
| Package | Path | Status | Responsibility |
|---|---|---|---|
@asase/core |
libs/asase/core |
Implemented | Foundation: branded IDs, enums, value objects, entities, services, db-schema |
@asase/crops |
libs/asase/crops |
Implemented | Crop registry, variety recommendation, pest/disease, field ops, irrigation, soil, health, labour, mechanization, yield, intercropping, harvest loss, weather |
@asase/livestock |
libs/asase/livestock |
Implemented | Livestock registry, vaccination, feed formulation, broiler/layer/hatchery, disease surveillance, mortality, house environment, distribution, aquaculture (fish farm, growth, feed, health, water quality) |
@asase/infrastructure |
libs/asase/infrastructure |
Implemented | Redis cache, MinIO storage, event bus, Prometheus metrics, PostGIS geospatial |
@asase/processing |
libs/asase/processing |
Implemented | Plant digital twin, scheduling, raw material receiving, BOM, batch execution, recipes, utility/energy monitoring, yield/waste, batch genealogy, nutritional labeling, OEE, predictive maintenance, SPC, cost of quality |
@asase/cold-chain |
libs/asase/cold-chain |
Implemented | Facility registry, temperature monitoring, inventory, energy optimizer, backup power, transport fleet, grain storage, warehouse, inventory valuation, warehouse receipt (GCX), post-harvest loss, compliance docs, last-mile, route optimizer, excursion analytics |
@asase/supply-chain |
libs/asase/supply-chain |
Implemented | Procurement, outgrower, contract farming, import management, supplier risk, distribution network, vehicle routing, market channel, returns logistics, delivery proof, commodity price, price forecast, import parity, margin analysis, demand sensing |
@asase/quality |
libs/asase/quality |
Implemented | HACCP, audit, CCP monitoring, PRP, water quality, pesticide residue, aflatoxin, LIMS, recall, environmental compliance, regulatory change, label compliance, organic/export/FDA certification, calibration |
@asase/export |
libs/asase/export |
Implemented | Commodity analyzer, market scanner, grading, volume forecaster, competitor tracker, trade documents, AfCFTA, EU regulation, customs duty, license manager, buyer CRM, dynamic pricing, contract negotiation, logistics optimizer, certification tracker |
@asase/inputs |
libs/asase/inputs |
Implemented | Fertilizer blend optimizer, soil nutrient mapper, fertilizer cost, organic fertilizer advisor, subsidy tracker, seed performance/multiplication, agrochemical guidance, IPM advisor, agrochemical safety, input distribution, farmer credit, input bundle optimizer, import substitution, input quality assurance |
@asase/market-intel |
libs/asase/market-intel |
Implemented | Commodity/farmgate price tracking, price forecasting, price transmission, cedi exposure, supply-demand modeling, competitor analysis, consumer trend, price elasticity, seasonality profiler, AfCFTA opportunity, regional trade flow, market entry, trade intelligence, policy impact simulator |
@asase/retail |
libs/asase/retail |
Implemented | QSR location, franchise management, POS integrator, staff scheduling, quality audit, menu engineering, recipe cost, menu localizer, inventory waste, dynamic menu pricer, delivery logistics/platforms, institutional catering, central kitchen, customer loyalty |
@asase/financials |
libs/asase/financials |
Implemented | Startup cost, unit economics, farm/processing economics, working capital, consolidated projection, capex planning, debt capacity, tax optimization, investor return, synergy valuation, scenario planner, benchmarking, FX risk, impact metrics |
@asase/connectors |
libs/asase/connectors |
Implemented | Cross-domain connectors to Brigid, Cybele, Freya, Saraswati, Maat, Aje |
@asase/sota |
libs/asase/sota |
Implemented | Satellite remote sensing, drone/precision agriculture, computer-vision grading, blockchain traceability + IoT cold chain, ML yield prediction + RL crop planning |
@asase/migrations |
libs/asase/migrations |
Implemented | Drizzle migration runner, 11 migration files, 8 seed scripts, connection pool config |
@asase/core Source Modules#
@asase/core is the only library that other Asase libraries are allowed to
import directly. It is deliberately layered (see architecture.md §3) so that
each file carries only the imports it needs. The table below maps each source
file to its responsibility.
| Module | File | Responsibility |
|---|---|---|
| Types | types.ts |
Branded IDs, brand creators, enums, value objects, entity interfaces |
| Constants | constants.ts |
Crop varieties, livestock breeds, regulatory bodies, season ranges, markets, food-safety standards, HS codes, exchange rates, storage temperatures, soil classifications, post-harvest loss rates, BU prefixes, region codes, max batch sizes |
| Business Units | business-units.ts |
Per-unit config interfaces, discriminated union, type guards |
| Agro-ecology | agro-ecology.ts |
Zone enum, 16 region profiles, region/zone queries |
| Measurement | measurement.ts |
Phantom-typed mass/volume/area/temperature/humidity/currency units and conversions |
| Seasonality | seasonality.ts |
Crop seasonality profiles, planting windows, harvest/input-schedule resolution |
| Stakeholders | stakeholders.ts |
8 stakeholder profile types, discriminated union, type guards, compliance helpers |
| Domain Entities | domain-entities.ts |
CropVariety, FarmPlot, Facility hierarchy, Product, PricePoint/PriceTrend |
| Domain Services | domain-services.ts |
UnitConversionService, SeasonalCalendarService, GhanaRegulatoryService, GeolocationService, AuditTrailService |
| Unit Data | unit-conversion-data.ts |
Shared mass/volume/area conversion-factor maps |
| DB Schema | db-schema.ts |
Drizzle ORM: 27 pgEnum types, 36 tables, custom vector pgvector type |
| Validation | validation.ts |
Domain validators returning ValidationResult; COCOBOD cocoa grading |
| Utils | utils.ts |
Yield, harvest estimate, soil pH, currency, cold chain compliance, HS code, season, post-harvest loss, batch number, phone |
| Geo Utils | geo-utils.ts |
Haversine distance, DMS conversion, midpoint, Ghana-bounds check |
| Errors | errors.ts |
AsaseError hierarchy |
3. Core Data Model (@asase/core/types.ts)#
This section documents every type exported from types.ts. The file is the
vocabulary of the Asase domain: branded identifiers, enums, literal-union types,
value objects, and entity interfaces. Changes here affect every other library in
the domain.
3.1 Branded ID Types#
Branded ID types prevent passing a PlotId where a FarmId is expected — the
TypeScript compiler rejects the assignment even though both are strings at
runtime. Each branded type comes with a factory constructor.
Each is Brand<string, '<Name>'> with a matching create<Name>Id(id: string)
constructor:
FarmId, PlotId, CropId, LivestockId, BatchId, FacilityId,
ShipmentId, OrderId, SupplierId, CustomerId, WorkerId.
Constructors: createFarmId, createPlotId, createCropId,
createLivestockId, createBatchId, createFacilityId, createShipmentId,
createOrderId, createSupplierId, createCustomerId, createWorkerId.
3.2 Enums#
All enums use the const object + companion type pattern —
(typeof X)[keyof typeof X] — rather than TypeScript enum declarations, which
avoids the reverse-mapping overhead and keeps values tree-shakeable. The
BusinessUnit enum is the discriminant for the 19-member config union in
business-units.ts. The Region enum covers exactly Ghana's 16 administrative
regions in their official English spellings.
| Enum | Values |
|---|---|
BusinessUnit |
bakery, cafe, processed_foods, plant_farms, aquaculture, cold_chain, export_processing, animal_feed, institutional_catering, agricultural_inputs, beverages, poultry, dairy, edible_oils, rice_milling, spices, cassava_processing, qsr_chains, fertilizer (19) |
CropCategory |
cereal, legume, root_tuber, fruit, vegetable, oil_crop, spice, stimulant, fiber, fodder |
GrowthStage |
dormant, germination, seedling, vegetative, flowering, fruiting, maturation, harvest, post_harvest |
LivestockType |
cattle, poultry_broiler, poultry_layer, goat, sheep, pig, rabbit, fish_tilapia, fish_catfish, shrimp, snail |
ProcessingStage |
raw_material, cleaning, sorting, processing, packaging, storage, dispatch |
QualityGrade |
premium, grade_a, grade_b, grade_c, reject |
StorageCondition |
ambient, chilled, frozen, controlled_atmosphere |
TransportMode |
truck_refrigerated, truck_ambient, motorcycle, bicycle, rail, vessel |
CurrencyCode |
GHS, USD, EUR, GBP |
Region |
Greater_Accra, Ashanti, Western, Central, Eastern, Northern, Upper_East, Upper_West, Volta, Bono, Bono_East, Ahafo, Savannah, North_East, Oti, Western_North (16) |
Season |
major_rainy, minor_rainy, harmattan, dry |
UnitOfMeasure |
kg, tonnes, liters, pieces, bags_50kg, bags_100kg, crates, bunches |
3.3 Literal-Union Types#
These types are simpler than full enums — they are plain TypeScript
type = 'a' | 'b' | 'c' definitions used where the set of values is small and
does not need to be iterated programmatically.
| Type | Values |
|---|---|
SoilPHClassification |
strongly_acidic, moderately_acidic, slightly_acidic, neutral, slightly_alkaline, moderately_alkaline, strongly_alkaline |
SoilType |
sandy, loamy, clay, sandy_loam, clay_loam, silt_loam, laterite, alluvial, savannah_ochrosol, forest_ochrosol |
IrrigationType |
rainfed, drip, sprinkler, furrow, flood, bucket, dam_fed, borehole |
PlotStatus |
active, fallow, preparation, harvested, abandoned |
HealthStatus |
healthy, under_observation, sick, quarantined, treated, recovered |
ShipmentStatus |
pending, loading, in_transit, at_checkpoint, delayed, delivered, returned |
AreaUnit (types.ts) |
hectares, acres, sq_meters |
3.4 Value Objects#
Value objects carry domain semantics with their data. Temperature is always
stored in Celsius (never raw numbers); SoilPH carries its classification
alongside the raw value; CurrencyAmount always names its currency. All fields
are readonly. The helper functions below each table construct instances
safely.
| Interface | Fields | Notes |
|---|---|---|
GeoLocation |
latitude: number, longitude: number, altitude?: number, accuracy?: number |
All readonly |
Temperature |
celsius: number |
Always stored in Celsius |
Humidity |
percentage: number |
0–100 |
SoilPH |
value: number (0–14), classification: SoilPHClassification |
Built by createSoilPH(value) |
CurrencyAmount |
amount: number, currency: CurrencyCode |
|
DateRange |
start: Date, end: Date |
|
PlotArea |
value: number, unit: AreaUnit |
'hectares' | 'acres' | 'sq_meters' |
YieldPerHectare |
kgPerHectare: number |
Value-object helpers: temperatureFromCelsius, temperatureFromFahrenheit,
temperatureToFahrenheit, temperatureToKelvin, createSoilPH,
plotAreaToHectares, plotAreaToAcres, yieldToTonnesPerHectare.
3.5 Domain Entity Interfaces#
These are the core domain entity shapes stored in the database (via Drizzle,
§15) and passed between service layers. All fields are readonly. The entities
defined here are intentionally lean — they contain identifying and status data
only, with richer value objects in domain-entities.ts (§9) for use-cases that
need full detail.
Farm — id: FarmId, name: string, ownerId: string, region: Region,
district: string, geoLocation: GeoLocation, plots: readonly PlotId[],
totalArea: PlotArea, registrationNumber: string, createdAt: Date,
updatedAt: Date.
Plot — id: PlotId, farmId: FarmId, name: string, area: PlotArea,
soilType: SoilType, irrigationType: IrrigationType,
currentCrop: CropId | null, status: PlotStatus.
CropCycle — id: string, plotId: PlotId, cropId: CropId,
plantingDate: Date, expectedHarvestDate: Date, growthStage: GrowthStage,
variety: string, seedSource: string.
LivestockBatch — id: LivestockId, facilityId: FacilityId,
type: LivestockType, breed: string, quantity: number, entryDate: Date,
expectedExitDate: Date, healthStatus: HealthStatus.
ProcessingBatch — id: BatchId, facilityId: FacilityId,
stage: ProcessingStage, inputMaterials: readonly string[],
outputProduct: string, startTime: Date, endTime: Date | null,
yieldKg: number, qualityGrade: QualityGrade.
ColdChainReading — id: string, facilityId: FacilityId,
sensorId: string, temperature: Temperature, humidity: Humidity,
timestamp: Date, isInRange: boolean.
Shipment — id: ShipmentId, origin: FacilityId,
destination: FacilityId, transportMode: TransportMode,
items: readonly ShipmentItem[], departureTime: Date, eta: Date,
currentLocation: GeoLocation | null, status: ShipmentStatus.
ShipmentItem — productName: string, quantity: number,
unit: UnitOfMeasure, batchId: BatchId | null.
MarketPrice — id: string, commodity: string, market: string,
price: CurrencyAmount, unit: UnitOfMeasure, date: Date, source: string.
QualityTest — id: string, batchId: BatchId, testType: string,
result: string, grade: QualityGrade, testedBy: WorkerId, testedAt: Date.
4. Business Unit Configuration (@asase/core/business-units.ts)#
Each of Asase's 19 business units has unique operational parameters — a bakery tracks oven count and flour source; a cold-chain unit tracks cubic metres of refrigerated storage and refrigerated truck count; a poultry unit tracks broiler birds per cycle and laying hens. Rather than using a single wide configuration record with many nullable fields, the system uses a discriminated union: each business unit has a dedicated config interface with only the fields it needs.
BusinessUnitConfig is a 19-member discriminated union keyed on type. Shared
supporting types:
FdaLicenceType—manufacturer,importer,exporter,retailer,distributor,warehouse,food_vendorQualityCertification—GhanaFDA,GSA,ISO_22000,HACCP,GLOBAL_GAP,FAIRTRADE,ORGANIC_GHANA,RAINFOREST_ALLIANCE,COCOBOD_CERT,AGOA_COMPLIANT,EU_ORGANICMarketChannel—wholesale,retail,export,institutional,b2b_food_service,direct_consumerColdStorageCapability—capacityCubicMeters,chilled,frozen,refrigerationUnits
The 19 config interfaces (BakeryConfig, CafeConfig, ProcessedFoodsConfig,
PlantFarmsConfig, AquacultureConfig, ColdChainConfig,
ExportProcessingConfig, AnimalFeedConfig, InstitutionalCateringConfig,
AgriculturalInputsConfig, BeveragesConfig, PoultryConfig, DairyConfig,
EdibleOilsConfig, RiceMillingConfig, SpicesConfig,
CassavaProcessingConfig, QsrChainsConfig, FertilizerConfig) each carry a
type discriminant plus unit-specific fields. Examples:
BakeryConfig—ovenCount,dailyCapacityKg,flourSource(local_mill | imported | both),fdaLicenceType,certifications,channelsPoultryConfig—broilerBirdsPerCycle,layingHens,eggsPerDay,slaughterCapacityPerHour,hasHatchery,certifications,channelsColdChainConfig—storageInstallations: ColdStorageCapability[],refrigeratedTrucks,insulatedVans,transitInsuranceValueGhs,certifications(nochannels)
BusinessUnitConfigMap maps each BusinessUnit value to its config type;
ConfigForBU<T> indexes it.
Type guards / helpers: isBakeryConfig, isCafeConfig,
isPlantFarmsConfig, isAquacultureConfig, isColdChainConfig,
isExportProcessingConfig, isPoultryConfig, isDairyConfig,
requiresColdChainTracking (true for cold_chain, export_processing,
dairy, aquaculture), requiresFdaLicence (true except plant_farms,
aquaculture, cold_chain), getMarketChannels.
5. Agro-Ecology (@asase/core/agro-ecology.ts)#
This module maps Ghana's 16 administrative regions to their agro-ecological
zones and encodes the seasonal planting calendar for each. Its central purpose
is to let the platform ask "given a GPS coordinate, what crops are appropriate
right now?" — answered by chaining getRegionForCoordinate → getRegionProfile
→ getRecommendedCropsForRegion and getActiveSeasonWindow.
AgroEcologicalZone const enum — coastal_savanna, deciduous_forest,
forest_savanna_transition, guinea_savanna, sudan_savanna.
IrrigationNeed — high, moderate, low, minimal.
SeasonWindow — plantingStartMonth, plantingEndMonth, harvestStartMonth,
harvestEndMonth (all number), primaryCrops: readonly string[].
GhanaRegionProfile — region, zone, rainfallRangeMm {min,max},
temperatureRangeCelsius {min,max}, dominantSoilTypes, majorSeasonWindow,
minorSeasonWindow: SeasonWindow | null (null for unimodal northern zones),
drySeasonIrrigationNeed, valueChainsNotes.
GHANA_REGION_PROFILES — a profile for all 16 regions. REGION_TO_ZONE maps
every region to its zone. Helpers: getRegionsByZone, getRegionProfile,
isBimodalRegion, getActiveSeasonWindow, getRecommendedCropsForRegion.
6. Measurement (@asase/core/measurement.ts)#
The measurement module solves a real agricultural problem: Ghanaian markets use
local units (olonka, maxi-bag) alongside international SI units, and confusing
them in calculations produces wrong-order-of-magnitude errors. The phantom-typed
algebra ensures that a Mass value cannot be accidentally added to an Area
value, and that conversions go through a single canonical SI path.
Phantom-typed Measurement<U, D> over dimensions
mass | volume | area | temperature | humidity | currency. The unit enums below
define every valid unit for each dimension; the Ghana-specific conversion
factors following the table are the authoritative values used by all conversion
functions.
| Unit enum | Values |
|---|---|
MassUnit |
g, kg, t, lb, oz, mini_bag_50kg, maxi_bag_100kg |
VolumeUnit |
ml, l, gal_us, m3, olonka, bowl, american_tin_small, american_tin_large |
AreaUnit (measurement) |
sqm, ha, ac, sqkm, plot |
TemperatureUnit |
C, F, K |
CurrencyMeasurementUnit |
GHS, USD, EUR, GBP |
Ghana-specific conversion factors: olonka = 2.5 L, bowl = 3.0 L,
american_tin_small = 0.375 L, american_tin_large = 0.8 L, plot = 0.3 ha,
mini_bag_50kg = 50 kg, maxi_bag_100kg = 100 kg.
Constructors/converters: mass, convertMass, toKg, volume,
convertVolume, toLitres, area, convertArea, toHectares, temperature,
convertTemperature, humidity (throws RangeError outside 0–100), money,
formatQuantity. Quantity<U> is a persisted { value, unit } pair;
MassQuantity/VolumeQuantity/AreaQuantity/TemperatureQuantity are
aliases. (measurement.ts's AreaUnit is re-exported as FarmAreaUnit from
the package barrel to avoid clashing with types.ts's AreaUnit.)
7. Seasonality (@asase/core/seasonality.ts)#
The seasonality module answers crop-calendar questions: "When should I plant Jasmine 85 rice in a bimodal rainfall zone?", "When is the next planting window for Obatanpa maize?", "Given a planting date for Afisiafi cassava, when is the expected harvest?". It encodes profiles for nine key Ghana crop varieties and exposes helper functions that take a crop key, planting date, and rainfall pattern and return actionable calendar guidance.
CropGrowthStage, RainfallPattern (bimodal | unimodal), CalendarMonth
(1…12).
PlantingWindow — season, startMonth, endMonth (CalendarMonth),
startDay, endDay (number), rainfallPattern, latenessRisk
(low | moderate | high).
CropDuration — minDays, maxDays, daysToFlowering, daysToHarvest.
InputApplicationWindow — inputType, daysAfterPlanting, windowDays,
rationale.
CropSeasonalityProfile — cropKey, name, plantingWindows, duration,
inputSchedule, postHarvestNotes.
CROP_SEASONALITY — profiles keyed by crop (MAIZE_OBATANPA, MAIZE_ABONTEM,
CASSAVA_AFISIAFI, RICE_JASMINE_85, COCOA_HYBRID, YAM_PONA,
GROUNDNUT_MANIPINTA, SOYBEAN_SARI_SOLIMO, TOMATO_PECTOMECH).
GHANA_SEASONALITY — SeasonalityDescriptor for bimodal and unimodal.
Functions: getPlantingWindowsForPattern(cropKey, pattern),
estimateHarvestRange(cropKey, plantingDate) → {earliest, latest} | null,
resolveInputSchedule(cropKey, plantingDate),
isInPlantingWindow(cropKey, date, pattern).
8. Stakeholders (@asase/core/stakeholders.ts)#
The stakeholder model captures the full cast of actors in Ghana's agricultural
value chain as a discriminated union. Each actor type carries the identity
documents, licences, and operational fields that are specifically relevant to it
— a farmer profile carries MoFA farmer number and mobile money provider; a
regulator profile carries inspection authority and regulatory domain. The
compliance functions (isFdaRegulated, requiresPprsdCompliance) operate on
the union type, making regulatory gate-checks type-safe and precise.
Identity-document type aliases: GhanaCardNumber,
TaxpayerIdentificationNumber, SsnitNumber, BusinessRegNumber,
MofaFarmerNumber (all string).
StakeholderContact — mobile, landline?, email?, address, district,
region.
StakeholderRole discriminant — farmer, processor, distributor,
retailer, exporter, input_supplier, financier, regulator.
Stakeholder is a discriminated union of 8 profiles, each extending
BaseStakeholder (id, role, name, contact, kycVerified,
onboardedAt):
| Profile | Key fields / sub-types |
|---|---|
FarmerProfile |
category (smallholder | commercial | outgrower | cooperative_member), economicGroup (subsistence | transition | commercial_small | commercial_medium | commercial_large), mofaFarmerNumber?, ghanaCardNumber?, ssnitNumber?, primaryCommodity, totalFarmAreaHectares, outgrowerSchemeName?, hasCreditAccess, usesMobileMoney, mobileMoneyProvider? (MTN | Vodafone | AirtelTigo), dependants? |
ProcessorProfile |
category (primary | secondary | tertiary), fdaLicenceNumber?, gsaCertification?, tin?, businessRegNumber?, monthlyCapacityTonnes, permanentEmployees, productCategories, haccpCertified, iso22000Certified |
DistributorProfile |
tier (national | regional | district | last_mile), refrigeratedVehicles, ambientVehicles, distributionRegions, offersColdChain, annualTurnoverGhsBand |
RetailerProfile |
retailerType (supermarket | mini_mart | market_stall | hawker | agro_dealer | cooperative_shop), sellsFreshProduce, sellsAgrochemicals, pprsdDealerNumber?, avgMonthlySalesGhs? |
ExporterProfile |
gepaNumber?, fdaLicenceNumber?, exportLicenceNumber?, destinationMarkets (ExportDestination[]), productCategories, annualExportValueUsd?, agoaBeneficiary |
InputSupplierProfile |
supplierType (national_distributor | regional_distributor | agro_dealer | manufacturer), pprsdNumber?, suppliesCertifiedSeeds, suppliesAgrochemicals, operatingRegions, subDealerCount? |
FinancierProfile |
financierType (microfinance | rural_bank | commercial_bank | fintech | agri_insurer | development_finance), bogLicenceNumber?, offersCropInsurance, offersMobileCredit, agriLoanPortfolioGhs? |
RegulatorProfile |
bodyType (Ghana_FDA | GSA | PPRSD | VSD | COCOBOD | GEPA | GRA | MOFA | EPA | NIA | Local_Government), regulatoryDomain, website?, issuesExportCerts, hasInspectionAuthority |
ExportDestination — EU, US, UK, ECOWAS, Middle_East, Asia,
Other.
Type guards: isFarmer, isProcessor, isDistributor, isRetailer,
isExporter, isInputSupplier, isFinancier, isRegulator.
isFdaRegulated(s) — true for processor/retailer/exporter.
requiresPprsdCompliance(s) — true for input_supplier or a retailer that sells
agrochemicals. getStakeholderDisplayName(s) formats "<name> (<RoleLabel>)".
9. Domain Entities (@asase/core/domain-entities.ts)#
Where types.ts (§3.5) defines lean entity interfaces for the core operational
loop, domain-entities.ts defines richer value objects for use-cases that need
full detail: crop variety botanical classification and yield ranges, farm plot
GPS polygons and rotation history, the facility hierarchy (processing plants,
cold stores, abattoirs), products with nutritional composition and bill of
materials, and price trend analytics.
9.1 CropVariety#
id, name, localNames: CropLocalNames (twi?, ewe?, ga?, dagbani?,
hausa?, fante?), botanical: BotanicalClassification (kingdom is the
literal 'Plantae', family, genus, species, binomial, cultivar?),
category: CropCategory, cocobodCode?, mofaRegistrationNumber?,
optimalZones, optimalRegions, growingDays {min,max},
yieldRange: YieldRange (minKgPerHa, typicalSmallholderKgPerHa,
attainableKgPerHa, maxKgPerHa), marketGrades: MarketGradeSpec[] (grade,
description, premiumPercent), ambientShelfLifeDays?,
coldStorageShelfLifeDays?, susceptibilities, resistances,
openPollinated, seedSavable.
CROP_VARIETY_CATALOG — keyed entries COCOA_HYBRID_CRIG,
MAIZE_OBATANPA_QPM, CASSAVA_AFISIAFI, YAM_PONA.
9.2 FarmPlot#
id: PlotId, farmId: FarmId, name, gpsPolygon?: GpsPolygon (array of
[lon, lat] pairs), areaHectares, soilType, soilPhValue?,
lastSoilTestDate?, irrigationType, status, currentCropVarietyId?,
currentPlantingDate?, rotationHistory: CropRotationEntry[], notes?.
CropRotationEntry — seasonYear, cropVarietyId, plantingDate,
harvestDate?, yieldKgPerHa?, qualityGrade?, inputCostGhs?.
9.3 Facility Hierarchy#
FacilityCategory — processing_plant, cold_storage, dry_warehouse,
abattoir, hatchery, feed_mill, fish_farm, shrimp_farm,
retail_outlet, market_centre, agro_input_store, laboratory.
FacilityOperationalStatus — active, under_maintenance, suspended,
decommissioned.
FacilityBase — id: FacilityId, businessUnit, category, name, region,
district, latitude, longitude, fdaLicenceNumber?, epaPermitNumber?,
lastFdaInspectionDate?, fdaInspectionResult?
(pass | conditional_pass | fail), operationalStatus, registeredAt.
Facility =
ProcessingFacility | ColdStorageFacility | AbattoirFacility | FacilityBase.
ProcessingFacility adds throughputTonnesPerDay, productCategories,
haccpImplemented, floorAreaSqm, processingLineCount. ColdStorageFacility
adds storageCubicMeters, temperatureRangeCelsius, refrigerationUnitCount,
hasBlastFreezer, backupGeneratorKva?. AbattoirFacility adds
vsdLicenceNumber?, slaughterCapacityPerDay, speciesSlaughtered,
anteMortemInspection, postMortemInspection.
9.4 Product#
id, sku, name, description, businessUnit, facilityId?,
lotTrackingEnabled, activeLotIds, billOfMaterials: BomEntry[],
nutritionalComposition?: NutritionalComposition, shelfLife: ShelfLifeParams,
gsaStandardReference?, fdaProductNumber?, cocobodGrade?, allergens,
organicCertified, halalCertified, salesUnit, netWeightGrams,
retailPriceGhs?, exportEligible, createdAt, updatedAt.
BomEntry — materialName, quantityPerUnit, unit, allergenRelevant.
NutritionalComposition — per-100g energyKcal, proteinG, fatG,
carbohydrateG, fibreG, sodiumMg, optional sugarG, calciumMg, ironMg,
vitaminCMg. ShelfLifeParams — ambientDays, chilledDays?, frozenDays?,
criticalWaterActivity?.
generateSku(businessUnitPrefix, categoryCode, sequence) →
"{PREFIX}-{CATEGORY}-{0000}".
9.5 PricePoint / PriceTrend#
PriceSource — ghana_commodity_exchange, esoko, mofa_market_survey,
market_field_visit, trader_report, export_contract, futures_cbot,
futures_ice, internal_transaction.
PricePoint — commodity, market, region, price, currency, unit,
source, observedAt, qualityGrade?, priceType
(wholesale | retail | farm_gate | export_fob), notes?.
PriceTrend — commodity, market, periodDays, openingPrice,
closingPrice, minPrice, maxPrice, meanPrice, changePercent,
volatilityPercent (coefficient of variation), observationCount, currency,
unit.
computePriceTrend(prices, commodity, market) returns PriceTrend | null (null
when fewer than 2 matching points). getLatestPrice(prices, commodity, market)
returns the most recent matching PricePoint.
10. Domain Services (@asase/core/domain-services.ts)#
Domain services wrap the lower-level modules (measurement, seasonality, agro-ecology, geo-utils) behind stateful class APIs that support dependency injection. A class that needs to convert units, look up planting windows, check regulatory requirements, resolve coordinates, or record audit events imports the appropriate service class and instantiates it — or receives it via constructor injection for testing.
10.1 UnitConversionService#
convertMass(value, from, to), convertVolume, convertArea (all return
ConversionResult<U> with
inputValue/inputUnit/outputValue/outputUnit/ conversionFactor); toKg,
toLitres, toHectares; bagCount(weightKg, bagSizeKg?: 50 | 100) →
{ fullBags, remainderKg }; pricePerKg(pricePerUnit, unit); formatMass,
formatArea.
10.2 SeasonalCalendarService#
getRainfallPattern(region) — unimodal for guinea/sudan savanna, else
bimodal. getPlantingAdvice(cropKey, region, date) → PlantingAdvice | null
(isWithinWindow, nextWindowStart?, daysUntilNextWindow?, latenessRisk?,
estimatedHarvestRange?, inputSchedule). getCropsInWindow(region, date),
buildAnnualCalendar(region, fromDate) (12-month planting calendar).
10.3 GhanaRegulatoryService#
getFoodSafetyStandard(commodity) → FoodSafetyResult | null (matched against
FOOD_SAFETY_STANDARDS). getRegulatoryBodies() returns REGULATORY_BODIES.
getExportRequirements(market: 'EU' | 'US' | 'UK' | 'ECOWAS' | 'Other') returns
phytosanitary, aflatoxin (maxAflatoxinPpbFresh/Processed), and MRL
requirements per market. getHsCode(commodity) → entry from HS_CODES.
getAgrochemicalRequirements(whoHazardClass: 'Ia' | 'Ib' | 'II' | 'III' | 'U')
returns PPRSD/EPA registration, storage class, and PPE.
10.4 GeolocationService#
Constructed with optional customMarkets; otherwise uses the 12-entry
MAJOR_MARKETS list. getRegionForCoordinate(lat, lon) — smallest-bounding-box
match over the 16 regions; getZoneForCoordinate;
findNearestMarkets(lat, lon, topN = 3) — Haversine ranking with road-distance
estimate (×1.3 factor) and travel hours (40 km/h); locate(lat, lon) →
GeolocationResult.
10.5 AuditTrailService#
AuditActorType — system, worker, manager, api_integration,
regulatory_inspector. ComplianceTag — EU_EXPORT, US_FDA, AGOA,
COCOBOD, GHANA_FDA, GSA_CERTIFIED, HACCP_CCP, ISO22000, GLOBAL_GAP.
AuditEvent — eventId, occurredAt, actor {type,id,name,ipAddress?},
action, resourceType, resourceId, businessUnit, previousState?,
newState?, changedFields?, complianceTags, reason?, correlationId?.
AuditStorageAdapter interface (save, query, getById) with
InMemoryAuditAdapter. AuditTrailService methods: record, recordCreate,
recordUpdate (computes changedFields by JSON diff), query, getHistory,
getComplianceEvents. Event IDs are EVT-<timestamp>-<6-digit-seq>.
11. Validation (@asase/core/validation.ts)#
Validation functions return a ValidationResult — a plain
{ valid: boolean, errors: readonly string[] } object — rather than throwing.
This makes validation usable in bulk-import pipelines and API handlers alike:
callers inspect valid and accumulate errors without needing try/catch. All
Ghanaian domain-specific constraints (phone number formats, farm registration
patterns, cocoa grading thresholds) are encoded here rather than scattered
across application code.
ValidationResult — { valid: boolean, errors: readonly string[] }.
The table below lists every validation function, its input parameters, and the constraint it enforces.
| Function | Behaviour |
| --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ----- |
| validateFarmRegistrationNumber(regNumber) | Matches GH-<2 letters>-<2-4 letters>-<3-6 digits> and validates the region code against REGION_CODES |
| extractRegionFromRegistration(regNumber) | Returns Region | null |
| validateGhanaCoordinates(location: GeoLocation) | Lat 4.5–11.5, lon −3.3–1.2; flags negative/over-900 m altitude and negative accuracy |
| validateCoordinates(location) | Generic lat −90…90, lon −180…180 |
| validateTemperatureForStorage(temp, condition) | Against STORAGE_TEMPERATURE_RANGES |
| validateTemperatureRange(temp, minCelsius, maxCelsius) | Custom range |
| validateMinimumGrade(actual, minimum) | QualityGrade rank order: premium < grade_a < grade_b < grade_c < reject |
| isExportableGrade(grade) | True for premium or grade_a |
| validateCocoaQuality(moisturePercent, defectivePercent, beanCountPer100g) | Returns { grade, issues } using COCOA_GRADE_THRESHOLDS (grade_1/grade_2/substandard/reject) |
| validateBatchSize(businessUnit, sizeKg) | Against MAX_BATCH_SIZES |
| validateCropCycleDates(plantingDate, expectedHarvestDate) | Planting before harvest; cycle 30–2555 days |
| validatePlantingDate(plantingDate, maxFutureDays = 365) | Rejects dates beyond the planning horizon |
| validateCurrencyAmount(amount, currency) | Non-negative, finite, supported currency |
| validateSoilPH(ph) | 0–14 |
| validateHumidity(percentage) | 0–100 |
| validatePlotArea(value, unit) | Positive; unit in hectares/acres/sq_meters; sanity caps |
| validateGhanaPhoneNumber(phone) | +233/233/0 prefix, 2x/5x network code, 7-digit subscriber number |
| validateBatchNumber(batchNumber) | XX-XXXXX-YYYYMMDD-NNN, with embedded-date sanity checks |
CocoaGradeThresholds — maxMoisturePercent, maxDefectivePercent,
minBeanCount100g, maxBeanCount100g. COCOA_GRADE_THRESHOLDS keys:
grade_1, grade_2, substandard.
12. Utilities (@asase/core/utils.ts)#
utils.ts contains standalone calculation functions that do not need to be
stateful or injected. These cover the domain-specific computations used
frequently enough to warrant shared helpers: yield, harvest estimation, soil pH
classification, currency conversion, cold chain compliance scoring, post-harvest
loss rates, batch number generation, and phone number formatting. The
estimateHarvestDate function applies regional climate factors (+5% days for
NORTHERN zones, +2% for TRANSITIONAL) to account for the shorter growing season
in southern Ghana versus the north.
calculateYieldPerHectare(totalYieldKg, area), compareYieldToTypical,
estimateHarvestDate(varietyKey, plantingDate, region) (midpoint of growing
days × regional climate factor: +5 % NORTHERN, +2 % TRANSITIONAL),
getGrowingPeriod, classifySoilPH, getCropSuitabilityForPH,
convertCurrency (via GHS intermediary using GHS_EXCHANGE_RATES),
formatCurrencyAmount, calculateColdChainCompliance (percentage of readings
in range plus worst breach), formatCommodityCode, isValidHSCode,
getSeasonForDate(date, region), isPlantingWindow(date, region),
calculatePostHarvestLoss(crop, storageCondition, durationDays) (compound loss
from POST_HARVEST_LOSS_RATES), generateBatchNumber, calculateBagCount,
getSuitableCropsForRegion, getVarietiesByCategory,
calculateTemperatureDeviation,
estimateWaterRequirement(cropCategory, growthStage, season),
formatGhanaPhoneNumber, identifyGhanaOperator
(MTN/Vodafone/AirtelTigo/Glo/Other).
13. Errors (@asase/core/errors.ts)#
The error hierarchy uses a base AsaseError class that all domain-specific
errors extend. Each error carries a code, statusCode (suitable for HTTP
responses), optional details, a timestamp, and an isOperational flag that
distinguishes expected domain errors (crop cycle closed, cold chain breach,
export compliance failure) from unexpected programming errors. AsaseError is
self-contained — it does not depend on a shared error base class from outside
the domain.
AsaseError (base; code, statusCode, details?, timestamp,
isOperational, toJSON()) and its hierarchy:
AsaseError
├── CropCycleError (plotId?, cropId?)
│ ├── InvalidPlantingDateError
│ └── CropCycleClosedError
├── ColdChainBreachError (getDeviationCelsius())
├── QualityFailureError
├── SupplyChainError (shipmentId?, origin?, destination?)
│ ├── ShipmentDelayError (delayHours)
│ └── RouteFailureError
└── ComplianceError (regulatoryBody?, standardCode?, violationType?)
├── FoodSafetyViolationError
└── ExportComplianceError
AsaseError is self-contained — it does not depend on a shared error base.
14. Constants (@asase/core/constants.ts)#
constants.ts holds the reference data that is stable enough to ship with the
domain library rather than require a database query: the crop variety catalog,
livestock breed list, regulatory bodies, seasonal ranges, market locations, food
safety standards, HS codes, exchange rates, storage temperature ranges, soil
classifications, post-harvest loss rates, business unit prefixes, region codes,
and batch size caps. These constants are the authoritative source for all
validation and calculation functions in the domain.
| Constant | Content |
|---|---|
CROP_VARIETIES |
CropVarietyInfo for ~35 Ghana cultivars (cocoa, maize, rice, cassava, yam, plantain, oil palm, shea, groundnut, cowpea, soybean, tomato, pepper, ginger, cashew, mango, pineapple, coconut, sorghum, millet, okra, garden egg, onion, cotton, turmeric) — each with localName, category, typicalYieldKgPerHa, growingDaysMin/Max, optimalRegions |
LIVESTOCK_BREEDS |
LivestockBreedInfo for ~21 breeds across cattle, poultry, goat, sheep, pig, fish, shrimp, rabbit, snail |
REGULATORY_BODIES |
MoFA, FDA, GSA, COCOBOD, EPA, PPRSD, VSD, FC (Fisheries Commission), GEPA — each with name, acronym, role |
SEASON_RANGES |
SOUTHERN, TRANSITIONAL, NORTHERN cropping-season date ranges |
REGION_CLIMATE_ZONE |
Each Region → SOUTHERN/TRANSITIONAL/NORTHERN |
MARKET_LOCATIONS |
12 major markets (Makola, Agbogbloshie, Kumasi Central, Tamale, Techiman, Bolgatanga, Cape Coast, Ho, Sunyani, Tema Port, Takoradi Port, Wa) with GPS and commodities |
FOOD_SAFETY_STANDARDS |
10 GSA/FDA standards (GS 34 maize, GS 207 rice, GS 52 cocoa, GS 44 gari, GS 972 shea butter, GS 55 palm oil, GS 955 fresh produce, GS 175 groundnuts, GS 215 dried fish, GS 83 cassava flour) |
HS_CODES |
20 HS tariff codes for key agricultural exports |
GHS_EXCHANGE_RATES |
Reference rates: GHS→USD/EUR/GBP and USD/EUR/GBP→GHS |
STORAGE_TEMPERATURE_RANGES |
Per StorageCondition: ambient 15–30 °C, chilled 0–5 °C, frozen −25…−18 °C, controlled_atmosphere 10–15 °C |
SOIL_CLASSIFICATIONS |
6 Ghana soil classes with optimal-pH range and suitable crops |
POST_HARVEST_LOSS_RATES |
Monthly loss rates per commodity × storage condition |
BUSINESS_UNIT_PREFIXES |
Two-letter batch prefix per business unit |
REGION_CODES |
Two-letter code per region (used by farm-registration validation) |
MAX_BATCH_SIZES |
Daily capacity cap (kg) per business unit |
15. Persistence — Drizzle Schema (@asase/core/db-schema.ts)#
The database schema is the persistence layer for the domain entities and
operational records defined in earlier sections. It uses the asase_ table
prefix throughout to prevent name collisions with other Oshun domain schemas in
the shared PostgreSQL instance. The schema defines its own custom vector
Drizzle type backed by the pgvector PostgreSQL extension (vector(1536)
default dimension, JSON-serialised driver values), enabling semantic crop
variety search via 1536-dimension embeddings.
The schema uses the asase_ table prefix throughout and defines a custom
vector Drizzle type backed by the PostgreSQL pgvector extension
(vector(1536) default, JSON-serialised driver values).
15.1 PostgreSQL Enums (27)#
PostgreSQL enum types enforce valid values at the database level, independent of
application-layer validation. The 27 pgEnum types listed below mirror the
TypeScript enums in §3.2 — when a TypeScript enum value changes, the
corresponding PostgreSQL enum migration must also be applied. Each enum name
carries the asase_ prefix.
asase_business_unit, asase_crop_category, asase_growth_stage,
asase_livestock_type, asase_processing_stage, asase_quality_grade,
asase_storage_condition, asase_transport_mode, asase_currency_code,
asase_region, asase_season, asase_unit_of_measure, asase_soil_type,
asase_irrigation_type, asase_plot_status, asase_health_status,
asase_shipment_status, asase_facility_type, asase_order_status,
asase_alert_severity, asase_certification_status, asase_haccp_record_type,
asase_worker_role, asase_listing_status, asase_trade_status,
asase_sensor_status, asase_breeding_method, asase_feed_type,
asase_input_category, asase_safety_class.
(asase_business_unit, asase_crop_category, asase_growth_stage,
asase_quality_grade, asase_region, asase_season, etc. mirror the
TypeScript enums in §3.2.)
15.2 Tables (36)#
The 36 tables are grouped by the domain concern they serve. All tables use
uuid primary keys (defaultRandom()), timezone-aware timestamp columns for
created_at / updated_at / deletedAt (soft delete), jsonb for flexible
metadata, and named B-tree / unique indexes.
| Group | Tables |
|---|---|
| Crops | asase_crop_varieties, asase_farms, asase_plots, asase_crop_cycles, asase_planting_records, asase_harvest_records |
| Livestock | asase_livestock_batches, asase_feeding_schedules, asase_health_records, asase_breeding_records |
| Facility/Processing | asase_facilities, asase_processing_batches, asase_bill_of_materials, asase_packaging_records |
| Cold chain | asase_cold_storage_units, asase_temperature_sensors, asase_sensor_readings, asase_breach_alerts |
| Supply chain | asase_suppliers, asase_purchase_orders, asase_shipments, asase_shipment_items, asase_delivery_tracking |
| Quality | asase_quality_standards, asase_quality_tests, asase_certifications, asase_haccp_records |
| Market | asase_market_prices, asase_commodity_listings, asase_trading_records, asase_price_forecasts |
| Operations | asase_business_unit_configs, asase_workers, asase_worker_assignments, asase_audit_log |
| Inputs | asase_agricultural_inputs |
Tables use uuid primary keys (defaultRandom()), timestamp with timezone
created_at/updated_at/deletedAt (soft delete), jsonb columns for
flexible metadata, foreign keys with onDelete rules, and named B-tree / unique
indexes. asase_crop_varieties carries a
vector('embedding', { dimensions: 1536 }) column for crop-similarity search.
asase_farms stores registration_number (unique), region, district, GPS
decimal columns, and certifications jsonb. asase_plots references
asase_farms (cascade) and asase_crop_varieties (set-null).
15.3 Migration Framework (@asase/migrations)#
The @asase/migrations package owns all database lifecycle operations for the
Asase domain: applying schema migrations, seeding reference data, and managing
connection pools. It is the only package that talks to the database by path —
all other libraries receive a database connection via dependency injection. The
CLI (migrate.ts) exposes the standard up, down, status, seed, and
reset commands as npm scripts.
- 11 migration files (
20260101_000001…_000011): create enums, crop tables, livestock tables, facility/processing tables, cold-chain tables, supply-chain tables, quality tables, market tables, ops tables, RLS policies, and the agricultural-inputs table. Exported asASASE_MIGRATIONS. - 8 seed scripts: business units, crop varieties, livestock breeds, facilities,
quality standards, markets, suppliers, workers (
runAllSeedsorchestrates them). AsaseMigrationRunner/createAsaseMigrationRunnerwithrunMigrations,rollbackMigration,getMigrationStatus,seedDatabase.- Connection pooling:
SENSOR_INGESTION_POOL,TRANSACTIONAL_POOL,REPORTING_POOLpresets,createAsasePool,AsaseConnectionManager,PGBOUNCER_CONFIG_TEMPLATE. - CLI
migrate.tswith commandsup,down,status,seed,reset(npm scriptsmigrate:up/down/status/seed/reset,drizzle:generate/push/ studio).
16. Infrastructure Services (@asase/infrastructure)#
@asase/infrastructure wraps shared Oshun platform services with Asase-
specific namespacing, type definitions, and configuration. It depends on
@asase/core, @oshun/cache, @oshun/event-bus, @oshun/logging,
@oshun/metrics, ioredis, and zod. All other Asase libraries that need
caching, storage, events, metrics, or geospatial queries import from
@asase/infrastructure — never directly from the underlying Oshun platform
packages.
Depends on @asase/core, @oshun/cache, @oshun/event-bus, @oshun/logging,
@oshun/metrics, ioredis, zod.
- Cache —
AsaseCacheClient,createAsaseCacheClient, key helpersasaseKey/asasePattern, predefined TTL constantsASASE_TTL. - Storage —
AsaseStorageService,ASASE_BUCKETS,BUCKET_CONFIGS,buildObjectKey,buildComplianceKey; types includeMinioClientLike,PresignOptions,BucketInitResult. - Events —
createAsaseEventBus,ASASE_TOPICS,ASASE_TOPIC_PATTERNS. Event types:CropsCycleStartedEvent,CropsHarvestRecordedEvent,CropsPestAlertEvent,LivestockHealthAlertEvent,LivestockMortalityRecordedEvent,ColdChainBreachDetectedEvent,SupplyChainDelayDetectedEvent,QualityTestRecordedEvent,MarketPriceUpdatedEvent.AsaseEventis the union;AsaseEventBaseis the shared base. - Metrics —
AsaseMetricsService,createAsaseMetrics; metric groupsCropMetrics,LivestockMetrics,ProcessingMetrics,ColdChainMetrics,SupplyChainMetrics,QualityMetrics,MarketMetrics. - Geospatial —
AsaseGeospatialService,GHANA_REGION_INFO,GEO_SQL,haversineDistanceKm,findRegionByCoordinate,sortByDistance,toPointWkt,toGeoJsonString,buildBufferSql; types includePlotBoundary,FacilityLocation,DeliveryRoute,MarketCatchmentArea,PgClientLike.
17. Domain Library API Surface (Selected)#
Each domain library exposes a curated index.ts barrel that re-exports the
public API. The lists below are representative entry points — the highest-value
exports that consumers are most likely to import. The full surface is in the
library source. For a narrative description of what each library does, see
features.md.
Each domain library exposes a curated index.ts barrel. The full surface is in
the library source; representative entry points:
@asase/crops—GHANA_CROP_REGISTRY,recommendVarieties,PEST_DISEASE_CATALOG,FieldActivityTracker,GHANA_INPUT_PRODUCTS+generateInputSchedule,GHANA_IRRIGATION_SCHEMES+estimateEToHargreaves/computeKcAtDas/generateIrrigationSchedule,LabourManager+ wage/compliance functions,MechanizationScheduler,INTERCROPPING_MATRIX+generateRotationPlan,predictYield,CropHealthMonitor+computeNdvi/computeEvi/computeNdwi,SoilFertilityTracker+GHANA_SRID_THRESHOLDS,WeatherImpactAnalyzer,HarvestLossEstimator.@asase/livestock—GHANA_LIVESTOCK_BREEDS+LivestockRegistry+generateNlisId,GHANA_VACCINE_CATALOG+VaccinationManager,FeedFormulationEngine+formulateRation,DiseaseSurveillanceSystem+generateWahisNotification,MortalityMorbidityService+computeEpef,BroilerFlockTracker,LayerFarmManager+GHANA_EGG_GRADE_THRESHOLDS,HatcheryManager+computePasgarScore,HouseEnvironmentController+computeThi,PoultryDistributionOptimizer,FishFarmRegistry,WaterQualityMonitor,AquaFeedManager,AquaGrowthTracker,FishHealthManager.@asase/processing—ProcessingPlantRegistry,ProductionScheduler,RawMaterialReceivingService,BomExplosionService,BatchExecutionEngine,RecipeManager,UtilityMonitoringService,YieldWasteTracker,BatchGenealogyTracker,NutritionalLabelingEngine,OEEEngine,EnergyEfficiencyAnalytics,PredictiveMaintenanceService,SPCService,COQReportingService.@asase/cold-chain—ColdStorageFacilityRegistry,TemperatureMonitoringService,ColdRoomInventoryService,EnergyOptimizationEngine,BackupPowerManager,TransportFleetManager,GrainStorageMonitor,WarehouseManager,InventoryValuationEngine,WarehouseReceiptManager(GCX),PostHarvestLossEngine,ComplianceDocumentGenerator,LastMileColdChainTracker,ColdChainRouteOptimizer,ExcursionAnalyticsEngine.@asase/supply-chain—ProcurementEngine,OutgrowerSchemeManager,ContractFarmingService,ImportManagementService,SupplierRiskRegistry,DistributionNetworkOptimizer,VehicleRoutingEngine,MarketChannelService,ReturnsLogisticsService,DeliveryProofService,CommodityPriceService,PriceForecastEngine,ImportParityService,MarginAnalysisService,DemandSensingEngine.@asase/quality—HaccpPlanManager,AuditManagementService,CcpMonitoringService,PrpTracker,WaterQualityService,PesticideResidueService,AflatoxinManagementService,LimsService,RecallManagementService,EnvironmentalComplianceService,RegulatoryChangeMonitoringService,LabelComplianceService,OrganicCertificationService,ExportCertificationService,FdaRegistrationService,CalibrationService.@asase/export— commodity analyzer,ExportMarketScanner,CommodityGradingEngine,ExportVolumeForecaster,CompetitorExportTracker,TradeDocumentGenerator,AfCFTAComplianceEngine,EURegulationTracker,CustomsDutyCalculator,ExportLicenseManager,ExportBuyerCRM,DynamicPricingEngine,ContractNegotiationAssistant,ExportLogisticsOptimizer,QualityCertificationTracker.@asase/inputs—FertilizerBlendOptimizer,SoilNutrientMapper,FertilizerCostAnalyzer,OrganicFertilizerAdvisor,FertilizerSubsidyTracker,SeedPerformanceDatabase,SeedMultiplicationTracker,AgrochemicalGuidanceEngine,IntegratedPestManagementAdvisor,AgrochemicalSafetyModule,InputDistributionNetworkManager,FarmerCreditFacilitator,InputBundleOptimizer,ImportSubstitutionAnalyzer,InputQualityAssurance.@asase/market-intel—CommodityPriceTracker,FarmgatePriceMonitor,PriceForecastingEngine,PriceTransmissionAnalyzer,CediExposureCalculator,SupplyDemandModeler,CompetitorAnalysisEngine,ConsumerTrendAnalyzer,PriceElasticityCalculator,SeasonalityProfiler,AfCFTAOpportunityScanner,RegionalTradeFlowMapper,MarketEntryAssessor,TradeIntelligenceDashboard,PolicyImpactSimulator.@asase/retail—QSRLocationAnalyzer,FranchiseManagementSystem,RestaurantPOSIntegrator,StaffSchedulingOptimizer,QualityAuditSystem,MenuEngineeringAnalyzer,RecipeCostCalculator,MenuLocalizer,InventoryWasteTracker,DynamicMenuPricer,DeliveryLogisticsEngine,DeliveryPlatformIntegrator,InstitutionalCateringManager,CentralKitchenPlanner,CustomerLoyaltyEngine.@asase/financials—StartupCostEstimator,UnitEconomicsModeler,FarmEconomicsCalculator,ProcessingEconomicsAnalyzer,WorkingCapitalModeler,ConsolidatedProjectionEngine,CapexPlanningModule,DebtCapacityAnalyzer,TaxOptimizationModeler,InvestorReturnCalculator,SynergyValuationEngine,ScenarioPlanner,BenchmarkingModule,FXRiskQuantifier,ImpactMetricsCalculator.@asase/connectors— Brigid (IrrigationInfrastructureConnector,ProcessingFacilityDesignBridge,ColdChainInfrastructurePlanner,RuralRoadAssessmentLink), Cybele (ClimateAdaptationConnector,SoilHealthIntegrator,WaterResourceLinker,BiodiversityImpactAssessor), Freya (AgriculturalMarketplaceConnector,PaymentReconciliationBridge,SupplyChainFinanceLinker), Saraswati (FarmerTrainingContentGenerator,AgriculturalResearchBridge), Maat (FoodSafetyComplianceConnector,LandTenureIntegrator), Aje (AgriculturalLendingConnector,CommodityHedgingBridge).@asase/sota—SatelliteCropMonitor,CropAreaEstimator,DeforestationAlertSystem,FloodDroughtEarlyWarning,DroneSurveyPlanner,DroneSprayingController,PlantCountAnalyzer,CacaoBeanGrader,CashewKernelClassifier,GrainQualityAnalyzer,BlockchainTraceabilityLedger,SmartContractPaymentSystem,IoTColdChainMonitor,ColdChainAnalyticsDashboard,MLYieldPredictor,CropDiseasePredictor,RLCropPlanningAgent,RLResourceAllocator.
18. Applications (apps/asase/*)#
The five application packages are the consumer-facing surfaces of the domain. They are implemented as TypeScript libraries (not Next.js or Express apps) — each exposes module-level service classes and functions that can be composed by an HTTP server, CLI, or other runtime. All five include Vitest specs.
All five applications are implemented as TypeScript libraries with src/
modules and Vitest specs.
| App | Path | Modules |
|---|---|---|
@asase/api |
apps/asase/api |
api-gateway.ts, api-auth.ts |
@asase/dashboard |
apps/asase/dashboard |
dashboard-shell.ts, kpi-view.ts, value-chain-viz.ts, alert-center.ts, reporting-engine.ts |
@asase/field |
apps/asase/field |
field-data-capture.ts, farmer-registration.ts, mobile-advisory.ts, input-distribution.ts, harvest-procurement.ts |
@asase/marketplace |
apps/asase/marketplace |
b2b-portal.ts, farmer-input-store.ts |
@asase/processing |
apps/asase/processing |
processing-dashboard.ts, batch-traceability.ts, qc-workstation.ts |
- Dashboard —
AsaseDashboardShell(role-based sessions/permissions),ConsolidatedKPIView+ASASE_BU_METRICS,ValueChainVisualization(margin waterfall, bottleneck ranking, flow maps),AlertManagementCenter(ESCALATION_RULES, priority scoring, escalation),ReportingEngine(templates, scheduled reports). - Field —
FieldDataCapture(offline sync queue),FarmerRegistrationModule(biometric enrolment, household categorisation),MobileAdvisorySystem(weather/market/agronomic advisories, USSD menu text, channel selection),InputDistributionTracker(QR verification, stock),HarvestProcurementModule(weight capture, grading, payment initiation). - Marketplace — B2B portal plus
FarmerInputStore(catalog, cart, Mobile Money order flow: place → pay → dispatch → confirm). - Processing — processing dashboard, batch traceability, QC workstation.
- API —
api-gateway.tsandapi-auth.ts(gateway + authentication).
19. Configuration#
Package Configuration#
{
"name": "@asase/core",
"version": "0.1.0",
"private": true,
"type": "module",
"dependencies": { "drizzle-orm": "catalog:", "zod": "catalog:" },
"devDependencies": { "vitest": "catalog:" }
}
Project Tags#
["scope:asase", "layer:domain", "type:lib"]
Environment Variables#
# @asase/migrations connection (DATABASE_URL accepted as fallback)
ASASE_DATABASE_URL=postgresql://...
20. Cross-Domain Integration#
Cross-domain integration is implemented entirely in @asase/connectors (see
§17). The connector pattern keeps domain boundaries clean: Asase never imports
from another Oshun domain library; instead, each connector owns typed payload
interfaces that translate Asase data into the vocabulary of the receiving
domain. The six domains Asase connects to, and the nature of each bridge:
- Brigid — engineering/infrastructure: Asase sends facility and irrigation requirements; Brigid returns engineering designs.
- Cybele — earth/environmental intelligence: Asase sends land-use and location data; Cybele returns climate and soil assessments.
- Freya — commerce/trade: Asase sends product listings and payment requests; Freya returns transaction records.
- Saraswati — knowledge/education: Asase sends agricultural practice data; Saraswati returns training content.
- Maat — governance/compliance: Asase sends compliance reports and land-tenure documents; Maat manages the regulatory lifecycle.
- Aje — financial intelligence: Asase sends farmer and commodity data; Aje returns lending scorecards and hedging structures.
Each connector is a class plus builder functions and typed payload interfaces.
21. External Data Sources#
The domain references several Ghanaian institutional data sources whose standards and formats are encoded directly in the codebase — not fetched at runtime, but compiled into constants and validation rules. The table below documents which external source backs each constant or validation.
| Source | Data referenced in code |
|---|---|
| MoFA farm registry | Farm registration number format and two-letter region codes (REGION_CODES) |
| COCOBOD grading standards | Cocoa quality thresholds (COCOA_GRADE_THRESHOLDS) |
| Ghana Standards Authority | FOOD_SAFETY_STANDARDS (GS … specifications) |
| Ghana Revenue Authority | HS_CODES for export commodities; import-duty schedules in supply-chain/export |
| Bank of Ghana / forex | GHS_EXCHANGE_RATES reference rates |
| Ghana Meteorological Agency | Season date ranges (SEASON_RANGES) and agro-ecological profiles |
| VSD / WOAH (OIE) | Livestock disease profiles and WAHIS notification (@asase/livestock) |
| GCX | Warehouse-receipt grading and fees (@asase/cold-chain) |