# Saraswati Domain — Architecture

> 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 `ev` imports
  `@saraswati/core` (in two files: `design/vehicle-design.ts` and
  `powertrain/powertrain.ts`). The other 16 redefine the types they need
  locally. `core` is 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-memory
  `Map` stores** (~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 under
  `libs/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.

```mermaid
flowchart TD
    consumers["Consumers<br/>(dashboards · partner domains)"]
    subgraph gw["@saraswati/gateway (Hono)"]
      mw["middleware: auth · rate-limit · metrics<br/>tracing · logger · circuit-breaker"]
      routes["routes/* — inline Zod +<br/>in-memory Map stores"]
      extra["GraphQL · gRPC defs · MQTT topics<br/>WebSocket/SSE PubSub · Kafka bus · CQRS"]
    end
    core["@saraswati/core<br/>7 type modules + branded IDs<br/>(NOCT calc · 400m flight guard)"]
    db["@saraswati/db<br/>Drizzle · PostGIS · TimescaleDB · pgvector"]
    bus["17 BU capability libs<br/>ev · battery · solar · … · financials<br/>(MOTOR_CATALOG · IRR · cell catalog)"]
    dash["4 dashboard libs<br/>command · fleet · factory · iot-platform"]
    contracts["@contracts/saraswati<br/>brigid · asase · freya · cybele · maat"]
    neighbors["Neighbor domains<br/>Brigid · Asase · Freya · Cybele · Maat"]

    consumers -->|HTTP / GraphQL / WS| gw
    mw --> routes --> extra
    core -. imported only by ev .-> bus
    contracts <--> neighbors
    consumers -->|typed contracts| contracts

    db -. implemented, not wired .-> gw
    bus -. not imported by .-> gw
    dash -. self-contained projections .-> bus
```

---

## 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.ts` runs a real in-process `PubSubBus`
  fanning typed `WSMessage` values 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 as `text/event-stream`. This path is live,
  not stubbed.
- **Kafka event bus** — `events/kafka-event-bus.ts` is a topic-modeling layer: a
  `buildTopicName(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-process `SaraswatiEventBus` class. Its
  own comment is explicit: _"For production use, replace with `kafkajs` or
  `@confluentinc/kafka-javascript`."_ It is an honest abstraction over a broker,
  not a live Kafka connection.
- **gRPC** — `proto/services.ts` is a set of TypeScript message-type interfaces
  for robotics/drone/IoT/manufacturing control, documented as _"generate from
  `.proto` files with protoc-gen-ts"_ in production. Definitions, not a running
  server.
- **MQTT** — `mqtt.ts` defines an AWS-IoT/HiveMQ-style topic hierarchy
  (`saraswati/{siteId}/{bu}/{entityId}/{stream}`) for device communication.
- **CQRS / event sourcing** — `cqrs/cqrs.ts` separates 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:

1. **Evidence integrity** — every regulated decision preserves the evidence
   packet, standard, jurisdiction, reviewer identity, and timestamp; compliance
   evidence is append-only once recorded.
2. **Telemetry identity** — ingested readings preserve source device identity
   and a `sequenceNumber`/`uplinkId` for ordering and deduplication.
3. **Versioned configuration** — firmware and device-config changes are
   versioned and reconstructable.
4. **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/db` is not imported by the
  gateway — REST routes persist to in-memory `Map` stores, 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 to `db` and 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.
