Architectural overview of the Saraswati advanced-technology bounded context: its library federation, the foundation/business-unit/dashboard layering, the gateway HTTP surface, and an honest account of what is wired together versus what is implemented but not yet composed.
Saraswati is the advanced-technology bounded context of the Oshun monorepo. It answers one sprawling question: how does a technology company design, manufacture, deploy, operate, and stay compliant across a wide portfolio of frontier industrial products — electric vehicles, batteries, solar systems, IoT devices, contract electronics, pharmaceuticals, robots, drones, telecom towers, medical devices, payment terminals, security systems, e-waste, 3D-printed parts, and satellite ground equipment? Rather than force a single universal "product" entity to cover every category, Saraswati carves each technology vertical into its own capability library with its own concrete entities, lifecycle enums, compliance records, and telemetry shapes.
The domain lives entirely under libs/saraswati/ (24 libraries) plus the
@contracts/saraswati package under libs/contracts/saraswati. There are no
apps/saraswati/* or services/saraswati/* packages — Saraswati is a
library-and-gateway domain. Roughly 350 tracked files carry it, of which ~34 are
Vitest suites. Consumers (cross-domain partners, dashboards) reach Saraswati's
HTTP surface through @saraswati/gateway, and reach its data shapes through
@saraswati/core and the cross-domain contracts.
A new engineer should understand one structural fact up front: Saraswati is a federation of independently-buildable libraries, not a strict top-down dependency tree. The libraries are unified by a shared naming convention, a shared design vocabulary (branded IDs, Zod validation, lifecycle status enums), and the gateway that fronts them — but they are deliberately loosely coupled at the import level. That looseness is the most important and most misread property of the domain, and the sections below are explicit about where wiring exists and where it does not.
The Three Library Groups#
libs/contracts/saraswati/ ← cross-domain integration contracts
libs/saraswati/
core/ db/ gateway/ ← foundation (types · persistence · HTTP boundary)
ev/ battery/ solar/ iot/ electronics/ pharma/ robotics/ drones/
telecom/ medical/ fintech-hw/ security/ ewaste/ additive/ satellite/
market-intel/ financials/ ← 17 business-unit capability libraries
command/ fleet/ factory/ iot-platform/ ← 4 cross-BU dashboard libraries
Each library is an Nx project with package.json, project.json,
tsconfig.json, a vitest.config.ts, and a src/index.ts barrel. Every
library carries its own src/ids.ts defining branded ID types and create*
helpers for its entities — so the ID discipline is replicated per library rather
than centralized. Every library builds, lints, and tests on its own.
Foundation: core, db, gateway#
@saraswati/core (libs/saraswati/core/src/) is the shared type catalog.
Its index.ts re-exports seven entity modules — vehicle.ts, energy.ts,
iot.ts, pharma.ts, robotics.ts, telecom.ts, manufacturing.ts — plus
ids.ts. Each module defines TypeScript interfaces, Zod schemas, type guards,
and factory functions for its slice of the portfolio, along with compile-time
branded ID types (VehicleId, BatteryPackId, DroneId, IoTDeviceId, …,
each a Brand<string, '…'>) so an ID of one kind cannot be passed where another
is expected. Crucially, core is not pure data: it embeds real domain
computation. energy.ts carries
calculateExpectedPanelOutput(panel, ambientTempC, irradianceWm2), which
applies a NOCT cell-temperature and irradiance correction; robotics.ts carries
isFlightPlanSafe, which encodes the Ghana GCAA 400 m AGL altitude cap as a
hard guard. These are domain-specific algorithms and invariants, not CRUD
scaffolding.
@saraswati/db (libs/saraswati/db/src/) is a real, runnable persistence
layer: a Drizzle ORM schema (schema.ts) over the saraswati PostgreSQL
database, plus connection.ts (pooling), migrations.ts, seed.ts, and
cache.ts (Redis key namespaces). migrations.ts installs the PostGIS,
TimescaleDB, and pgvector extensions via installExtensions(db) and configures
TimescaleDB hypertables for battery, solar, and IoT telemetry. The schema
defines shared enums (saraswatiStatus, saraswatiRegulatoryStatus, …) and
per-business-unit tables with PostGIS geometry columns and pgvector embedding
columns. This layer is complete and exercisable against a live database.
@saraswati/gateway (libs/saraswati/gateway/src/) is the HTTP boundary: a
Hono application (app.ts) that mounts the 17 business units under
/api/v1/{bu}/. It wraps every request in a production-grade middleware chain —
secureHeaders, CORS scoped to Oshun origins, distributed tracing,
structuredLogger with correlation IDs, Prometheus httpMetrics, a global 500
req/min rate limit plus per-BU limits via rateLimitForBU, and optionalAuth
(JWT). System endpoints expose /health, /ready (gated on circuit-breaker
state), /metrics, /openapi.json, /graphql, and /circuit-breakers. Beyond
REST, the gateway carries a GraphQL schema and executor (graphql/), gRPC
service definitions (proto/services.ts), an MQTT topic hierarchy (mqtt.ts),
WebSocket/SSE channels (routes/websocket.ts), a Kafka event-bus abstraction
(events/kafka-event-bus.ts), CQRS/event-sourcing primitives (cqrs/cqrs.ts),
API versioning, and a benchmarking harness.
The 17 business-unit capability libraries#
Each of ev, battery, solar, iot, electronics, pharma, robotics,
drones, telecom, medical, fintech-hw, security, ewaste, additive,
satellite, market-intel, and financials owns the full lifecycle for one
technology vertical. They are organized internally by concern — e.g.
libs/saraswati/ev/src/{design,powertrain,battery,chassis,certification,production,fleet,v2g,autonomous}/
and
libs/saraswati/battery/src/{cell,module,production,testing,stationary,second-life,next-gen}/.
These libraries contain the domain's real engineering content. ev's
powertrain/powertrain.ts ships a MOTOR_CATALOG of representative hub and
mid-drive motors with peak/continuous torque, efficiency, and thermal limits,
and a PowertrainConfigurator that selects a motor and sizes a drivetrain from
vehicle requirements. battery's cell/cell-catalog.ts carries manufacturer
cell specs (CATL, BYD, Samsung SDI, LG, EVE) with a comparison/grading engine.
financials's bu-models/bu-models.ts computes IRR with a real bisection
solver (computeIRR(cashFlows, tolerance = 1e-7, maxIter = 200)) and
portfolio/portfolio.ts computes NPV over a cash-flow series. Each library
verifies its own correctness in a *.test.ts suite, and the SOTA-flavored
verticals add a *-sota.test.ts.
The 4 cross-BU dashboard libraries#
command (technology operations: KPI aggregation, manufacturing status, supply
chain, quality, financial dashboard, regulatory tracker, alert center), fleet
(vehicle/drone fleet management), factory (manufacturing management: MES,
pharma dashboard, battery/solar/print-farm lines, NCR manager), and
iot-platform (device registry, smart-city ops, rule engine, OTA, data export)
aggregate operational views that span multiple business units. They own
projection and roll-up logic — not business rules — and each carries its own
ids.ts and snapshot types.
How the Libraries Actually Relate#
The single most important architectural correction to make against any "layered foundation" reading is that the import graph is far looser than the naming suggests. Verified from the source:
- Business-unit libraries are self-contained. Of the 17, only
evimports@saraswati/core(in two files:design/vehicle-design.tsandpowertrain/powertrain.ts). The other 16 redefine the types they need locally.coreis therefore best understood as a comprehensive parallel type catalog and a home for shared cross-cutting types, not a base that every BU compiles against. - The gateway does not import the business-unit libraries. Each route module
(
routes/ev.ts,routes/battery.ts,routes/remaining-bus.ts, …) declares its own inline Zod request schemas and serves from process-local in-memoryMapstores (~30 across the route files). The gateway is a complete, exercisable HTTP API in its own right; it is not a thin shell over the BU computation modules. - The gateway does not import
@saraswati/db. No file underlibs/saraswati/gateway/src/references@saraswati/db. The Drizzle persistence layer and the gateway are both implemented but are not yet wired to each other — the HTTP API currently persists to memory, and the database layer is driven independently. - The dashboard libraries do not import the business-unit libraries. They are self-contained projections that compute over data shapes passed to them, not live readers of BU state.
This is a deliberate composition style: maximally independent, individually buildable libraries unified by convention and by the gateway's HTTP contract. The cost is that "all 17 BUs build on the foundation" is aspirational at the import level; the benefit is that any library can be developed, tested, and shipped without dragging in the rest of the domain.
Eventing, Streaming, and Real-Time Seams#
Saraswati models several real-time transports. Each is implemented as far as the sandbox honestly allows, with explicit seams where a managed broker would otherwise be required:
- WebSocket / SSE —
routes/websocket.tsruns a real in-processPubSubBusfanning typedWSMessagevalues to subscribers across eight channels (ev_telemetry,battery_alerts,solar_live,iot_stream,drone_tracking,manufacturing_events,security_alarms,system_health); the SSE endpoint streams a channel astext/event-stream. This path is live, not stubbed. - Kafka event bus —
events/kafka-event-bus.tsis a topic-modeling layer: abuildTopicName(bu, category)convention (saraswati.{bu}.{telemetry|commands|events|alerts|audit}), a partition-key strategy (round-robin for telemetry, entity-keyed for ordering), DLQ naming (saraswati.dlq.{topic}), and an in-processSaraswatiEventBusclass. Its own comment is explicit: "For production use, replace withkafkajsor@confluentinc/kafka-javascript." It is an honest abstraction over a broker, not a live Kafka connection. - gRPC —
proto/services.tsis a set of TypeScript message-type interfaces for robotics/drone/IoT/manufacturing control, documented as "generate from.protofiles with protoc-gen-ts" in production. Definitions, not a running server. - MQTT —
mqtt.tsdefines an AWS-IoT/HiveMQ-style topic hierarchy (saraswati/{siteId}/{bu}/{entityId}/{stream}) for device communication. - CQRS / event sourcing —
cqrs/cqrs.tsseparates command and query paths, appending domain events and reconstituting aggregates by replay.
Read these as a coherent eventing design with one live in-process bus and clearly-labelled boundaries where external infrastructure plugs in.
Cross-Domain Integration#
@contracts/saraswati is the only sanctioned crossing point between Saraswati
and its neighbors. Its index.ts re-exports five modules, each a set of Zod
schemas plus typed adapter result interfaces:
brigid.ts— Saraswati manufacturing ↔ Brigid industrial automation (CEM production orders against IPC-7711/7721 SMT accuracy classes, energy-system integration, robotics, a shared MES event bus, predictive-maintenance sharing).asase.ts— EV fleet / drones / IoT / solar ↔ Asase agriculture (delivery fleets, agricultural drones, soil/weather IoT, cold chain, solar irrigation).freya.ts— Saraswati ↔ Freya e-commerce (last-mile fleet, smart-retail IoT, packaging electronics, fintech-hardware deployment, warehouse robotics).cybele.ts— Saraswati ↔ Cybele construction (construction robotics, smart-building IoT, EV-charging planning, rooftop solar, data-center equipment, survey drones).maat.ts— R&D / IP / PLM ↔ Maat knowledge management (TRL tracking, IP portfolio, PLM sharing, technology scouting, standards tracking).
The contract boundary keeps Saraswati's internal model free to change while
giving each consumer a typed, versioned slice rather than general access to all
17 business units. Two further boundaries are enforced by convention rather than
contract: Oya owns drone flight and swarm primitives that
@saraswati/drones operations build on, and Galatea owns humanoid embodied
AI where @saraswati/robotics extends only into task-specific industrial
machines. cross-domain.test.ts validates the contract schemas.
Compliance as a Cross-Cutting Concern#
Seven categories are regulated — pharma, medical devices, fintech hardware, EVs,
batteries, telecom, and e-waste — and each owns a category-specific compliance
entity rather than a shared one, because the concepts do not generalize: a GMP
BatchRecord (with qualified-person sign-off and Deviation tracking) is
nothing like a PCI PTS/DSS certificate, an NCA tower permit, or a UN-ECE vehicle
homologation record. The domain enforces four cross-cutting invariants:
- Evidence integrity — every regulated decision preserves the evidence packet, standard, jurisdiction, reviewer identity, and timestamp; compliance evidence is append-only once recorded.
- Telemetry identity — ingested readings preserve source device identity
and a
sequenceNumber/uplinkIdfor ordering and deduplication. - Versioned configuration — firmware and device-config changes are versioned and reconstructable.
- Model-assumption provenance — financial and generation projections retain their inputs and model version so they can be re-derived.
Guards in core encode hard rules directly: isBatchReleaseReady (QC passed,
status qc_testing, all deviations closed or minor), requiresNotifiedBody
(medical class IIb/III), requiresClinicalTrial, isFlightPlanSafe (the 400 m
cap). Changes to regulated libraries are expected to add contract, compliance,
audit, and data-retention tests on top of the standard lint/typecheck/unit
coverage.
SOTA and Next-Generation Modules#
Several verticals carry forward-looking analysis and planning modules under
sota/ or next-gen/ directories. These are real computational tools, not
deployed systems, and should be read as decision-support:
drones/src/sota/swarm-planner.ts computes multi-drone survey coverage and 3-D
conflict detection; security/src/sota/quantum-safe.ts performs post-quantum
algorithm sizing and a q-day threat-timeline assessment; battery/src/next-gen/
tracks solid-state, sodium-ion, EU battery-passport, and recycling readiness;
telecom/src/sota/6g-tracker.ts and satellite/src/sota/leo-planner.ts follow
the same tracker/planner pattern. They compute against real parameters but do
not control fielded hardware.
Status Summary — Implemented vs. Not Yet Wired#
- Implemented and self-consistent: all 24 libraries plus contracts build,
lint, and test independently;
core's type catalog and domain calculators; the BU capability libraries' domain algorithms (powertrain config, cell catalogs, NPV/IRR, coverage planning); the gateway's full middleware chain, REST surface, GraphQL schema/executor, in-process PubSub bus, and topic/CQRS modeling; the Drizzle/PostGIS/TimescaleDB/pgvector schema and migrations; the five cross-domain contracts. - Implemented but not composed:
@saraswati/dbis not imported by the gateway — REST routes persist to in-memoryMapstores, so the HTTP API and the database layer are not yet a single pipeline. The 17 BU computation libraries are not imported by the gateway either; the route handlers reimplement validation inline. Wiring the gateway todband to the BU libraries is the domain's primary integration gap. - Honest infrastructure seams: the Kafka bus, gRPC definitions, and MQTT topics model their transports but defer to external brokers/codegen in production, as their own comments state.
A note on a stale comment: gateway/src/app.ts opens with "All 19 business
units are mounted," but the code mounts and reports exactly 17
(buCount: 17). Seventeen is correct; the 19 is a leftover.
Verification Expectations#
The bar for regulated categories is deliberately higher than for ordinary code,
because errors in pharma, medical, or fintech logic carry legal and safety
consequences. Every change requires package-level lint, typecheck, and test
coverage. Regulated domains — pharma, medical devices, fintech hardware, EVs,
batteries, telecom, and e-waste — additionally require contract, compliance,
audit, and data-retention tests, and any change to a core guard that encodes a
regulatory invariant (the 400 m cap, batch-release readiness, notified-body
thresholds) must be covered by a test asserting the specific rule, not merely
the data shape.