# Brigid Domain - Technical Specifications

> Industrial Automation Intelligence. **Implemented** workspace domain —
> `libs/brigid/*` (24 library packages), `apps/brigid/*` (5 application
> services). TODO Phase 59.
>
> This specification is grounded entirely in the source under `libs/brigid/` and
> `apps/brigid/`. Every type, enum, schema, table, route, and event below traces
> to a named file in that tree. Where a capability is described in `features.md`
> or `TODOS/phase-59.md` but is not yet expressed as a concrete type or table,
> it is marked `(planned)`.

This document is the authoritative type-level and schema-level reference for the
Brigid domain. It complements `features.md` (which explains what each capability
does and why) with the exact field names, enum values, table schemas, route
signatures, and invariants that engineers need when writing or reviewing code.
Sections follow the same top-level grouping as `features.md` so the two
documents can be read in parallel.

## 1. Package Inventory

### 1.1 Library Packages (`libs/brigid/*`)

The table below lists every library package, its directory, and its primary
role. All packages declare `version` `0.1.0` except `@brigid/weighing` and
`@brigid/training`, which declare `1.0.0`. Every package is `type: module`,
exports its barrel from `./src/index.ts`, and ships `package.json`,
`project.json`, `tsconfig.json`, and `vitest.config.ts`.

| Package                     | Directory                       | Role                                                                                                                   |
| --------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `@brigid/core`              | `libs/brigid/core`              | Industrial type system, Zod schemas, unit conversions, engineering and data-quality validators, standards reference    |
| `@brigid/db`                | `libs/brigid/db`                | Drizzle ORM schema, post-migration SQL, seed data                                                                      |
| `@brigid/factory`           | `libs/brigid/factory`           | Production line design, PLC, SCADA, HMI, communications, motion, safety, batch                                         |
| `@brigid/machines`          | `libs/brigid/machines`          | Custom machine design workflow, mechanical, electrical, BOM/assembly, compliance                                       |
| `@brigid/ai-industrial`     | `libs/brigid/ai-industrial`     | Computer vision, predictive maintenance, process optimization, robotics AI, edge AI, SOTA, API types                   |
| `@brigid/energy`            | `libs/brigid/energy`            | Solar PV, BESS, grid/hybrid, power quality, Ghana energy specifics                                                     |
| `@brigid/maintenance`       | `libs/brigid/maintenance`       | Condition monitoring, CMMS, spare parts, KPI analytics, remote/IoT                                                     |
| `@brigid/robotics`          | `libs/brigid/robotics`          | Cobot deployment, robot programming, AGV/warehouse, robot safety                                                       |
| `@brigid/digital-twin`      | `libs/brigid/digital-twin`      | Factory twin, equipment twin, process simulation, virtual commissioning                                                |
| `@brigid/cybersecurity`     | `libs/brigid/cybersecurity`     | OT/ICS security assessment, network security, threat detection, access control                                         |
| `@brigid/mining`            | `libs/brigid/mining`            | Fleet logistics, process automation, mine safety and environment                                                       |
| `@brigid/oil-gas`           | `libs/brigid/oil-gas`           | Upstream, midstream, downstream, safety and compliance                                                                 |
| `@brigid/packaging`         | `libs/brigid/packaging`         | Primary/secondary packaging, line optimization, inspection, packaging materials                                        |
| `@brigid/agricultural-mech` | `libs/brigid/agricultural-mech` | Irrigation, greenhouse, post-harvest, livestock/aquaculture                                                            |
| `@brigid/water`             | `libs/brigid/water`             | Water treatment, wastewater, industrial effluent                                                                       |
| `@brigid/hvac`              | `libs/brigid/hvac`              | HVAC design, refrigeration, pharma cold storage, energy compliance                                                     |
| `@brigid/training`          | `libs/brigid/training`          | Curriculum, competency assessment/certification, learning delivery                                                     |
| `@brigid/materials`         | `libs/brigid/materials`         | Plastics recycling, welding consumables, industrial gases                                                              |
| `@brigid/market-intel`      | `libs/brigid/market-intel`      | Market analysis, sector demand, business development                                                                   |
| `@brigid/financials`        | `libs/brigid/financials`        | Business-unit models, pricing/costing, portfolio analysis                                                              |
| `@brigid/supply-chain`      | `libs/brigid/supply-chain`      | Logistics, planning                                                                                                    |
| `@brigid/weighing`          | `libs/brigid/weighing`          | Weighing systems, calibration management (OIML / ISO 17025 / GUM)                                                      |
| `@brigid/cross-domain`      | `libs/brigid/cross-domain`      | Integration adapters and Zod API contracts for Asase, Freya, Cybele, Saraswati, Maat                                   |
| `@brigid/sota-enhancements` | `libs/brigid/sota-enhancements` | Human-centric automation, edge AI, 5G remote ops, AR/VR, generative AI, RL, federated learning, digital thread/quantum |

### 1.2 Application Packages (`apps/brigid/*`)

Five applications expose the domain libraries as operational services. Note that
three application package names differ from their directory names, as described
after the table.

| Package                  | Directory                 | Role                                 |
| ------------------------ | ------------------------- | ------------------------------------ |
| `@brigid/api`            | `apps/brigid/api`         | Hono HTTP/SSE/WebSocket API surface  |
| `@brigid/factory-os`     | `apps/brigid/factory-os`  | Factory operations dashboard modules |
| `@brigid/energy-ms`      | `apps/brigid/energy`      | Energy management system modules     |
| `@brigid/maintenance-ms` | `apps/brigid/maintenance` | Maintenance management modules       |
| `@brigid/training-lms`   | `apps/brigid/training`    | Training academy / LMS modules       |

Note the package names differ from the directory names for three apps:
`apps/brigid/energy` is `@brigid/energy-ms`, `apps/brigid/maintenance` is
`@brigid/maintenance-ms`, `apps/brigid/training` is `@brigid/training-lms`.
`@brigid/energy-ms` (app) and `@brigid/energy` (library) are distinct packages.

### 1.3 Canonical Package Prefix

All Brigid packages — both libraries and applications — use the `@brigid/*`
prefix.

Cross-domain contracts are provided in-domain by `@brigid/cross-domain` (Zod
schemas in `cross-domain/src/api-contracts.ts`). The `libs/brigid` README also
references a separate `@contracts/brigid` package; the authoritative implemented
contract code is in `@brigid/cross-domain`.

---

## 2. Core Industrial Type System — `@brigid/core`

`@brigid/core` is the shared vocabulary that every other Brigid package depends
on. Because all domains — factory, energy, maintenance, robotics, security —
import their base types from here, a change to a core type has broad impact and
must be made carefully.

`@brigid/core/src/index.ts` re-exports nine modules: `equipment`, `maintenance`,
`energy`, `robotics`, `security`, `business`, `units`, `validators`,
`standards`, `schemas`. The type system is aligned to ISA-95, IEC 61131-3, ISO
12100, IEC 61511, IEC 62443, ISA-18.2, ISA-101, and OEE practice. Identifiers
throughout `@brigid/core` are plain `string` fields named `equipmentId`,
`sensorId`, `workOrderId`, etc.; there are no branded or opaque ID types in the
implementation.

### 2.1 Equipment & Asset Types (`equipment.ts`)

This module defines the physical-asset model: the hierarchy, the base equipment
record, and the specializations for machines, sensors, actuators, PLCs, SCADA
systems, HMIs, and production lines. Every other Brigid library addresses assets
using the identifiers and status values defined here.

#### 2.1.1 `EquipmentLevel`

The ISA-95 asset hierarchy defines how equipment is organized within a
manufacturing enterprise. Every asset carries one of these levels, which
determines where it lives in the addressing scheme for telemetry and alarms. The
full literal union is: `enterprise`, `site`, `area`, `production_line`,
`work_cell`, `equipment_unit`, `control_module`.

#### 2.1.2 `OEEMetrics`

Overall Equipment Effectiveness is the standard KPI for manufacturing
productivity. The `OEEMetrics` record decomposes OEE into its three components
plus the six big losses, and the schema enforces the mathematical identity so no
record can be stored with an inconsistent OEE value. Fields: `oee` (0–1),
`availability` (0–1), `performance` (0–1), `quality` (0–1),
`plannedProductionTimeHr`, `actualProductionTimeHr`, `idealCycleTimeSec`,
`actualCycleTimeSec`, `totalPartsProduced`, `goodParts`, `rejectedParts`, and
the six big losses: `equipmentFailureLossHr`, `setupAdjustmentLossHr`,
`minorStoppageLossHr`, `reducedSpeedLossHr`, `startupRejectLoss`,
`productionRejectLoss`. Invariant (enforced by `OEEMetricsSchema`): `oee` must
equal `availability × performance × quality` within 0.001.

#### 2.1.3 `Equipment`

`Equipment` is the base record for every physical asset in the system. All
specialized asset types (`Machine`, `Robot`, etc.) carry an `equipmentId` that
references an `Equipment` record. Fields: `equipmentId`, `name`, `description`,
`level` (`EquipmentLevel`), `parentId?`, `equipmentClass` (one of
`production_unit`, `storage_unit`, `process_cell`, `unit`, `equipment_module`,
`control_module`), `location` (`{ site, area, buildingOrBay?, coordinates? }`),
`manufacturer`, `model`, `serialNumber`, `assetTag`, `installDate` (ISO date),
`commissionDate?`, `warrantyExpiryDate?`, `status`, `oee?` (`OEEMetrics`),
`mtbfHours?`, `mttrHours?`, `tags` (`string[]`), `sensorIds` (`string[]`),
`actuatorIds` (`string[]`), `documentRefs` (`{ type, url }[]`).

`Equipment.status` literal union: `running`, `idle`, `maintenance`, `fault`,
`decommissioned`.

#### 2.1.4 `Machine` (extends `Equipment`)

`Machine` extends `Equipment` with the mechanical, electrical, and safety
parameters specific to production machinery. The `MachineCategory` union covers
the 20 most common industrial machine types, from CNC machining centres to AGVs.

`MachineCategory` literal union (20 values): `cnc_machining`,
`injection_moulding`, `press_forming`, `welding`, `assembly`, `conveyor`,
`robot_cell`, `packaging`, `inspection`, `testing`, `mixing`, `filling`,
`compressor`, `pump`, `heat_exchanger`, `reactor`, `extruder`, `crane_hoist`,
`agv`, `other`.

`Machine` adds: `category`, `dimensions` (`MachineDimensions`: `lengthMm`,
`widthMm`, `heightMm`, `weightKg`, `footprintM2`), `electrical`
(`MachineElectrical`: `voltageV`, `phaseCount` 1|3, `currentA`, `powerKW`,
`powerFactor?`, `protectionClass` IP rating, `hazardousAreaZone?` —
`Zone0`/`Zone1`/`Zone2`/`Zone20`/`Zone21`/`Zone22`/`none`), `capacity`
(`MachineCapacity` — throughput, cycle time, batch size, clamping force, spindle
RPM, axis travel, payload, pressure, temperature), `interfaces`
(`MachineInterface[]`), `plcId?`, `hmId?`, `firmware?`, `safetyCategory?`
(`Cat_B`..`Cat_4`), `performanceLevel?` (`PLa`..`PLe`), `operatingHours`,
`cycleCount`.

#### 2.1.5 `Sensor`

`Sensor` models a process instrument bound to one piece of equipment. The
`SensorPhysicalQuantity` enum covers the 24 measurands that industrial sensors
typically measure, and `SensorOutputType` covers the common signal protocols.
These two unions determine how the sensor tag is validated and how its reading
is interpreted downstream.

`SensorPhysicalQuantity` literal union (24 values): `temperature`, `pressure`,
`differential_pressure`, `flow`, `level`, `vibration`, `proximity`, `force`,
`torque`, `current`, `voltage`, `power`, `humidity`, `gas_concentration`,
`position`, `speed`, `acceleration`, `strain`, `ph`, `conductivity`,
`turbidity`, `dissolved_oxygen`, `weight`, `light`.

`SensorOutputType` literal union: `4-20mA`, `0-10V`, `HART`, `Modbus`,
`PROFIBUS`, `IO-Link`, `digital`, `RS485`, `wireless`.

`Sensor` fields: `sensorId`, `tag` (ISA-5.1 instrument tag, e.g. `TT-101`),
`name`, `quantity`, `unit`, `rangeMin`, `rangeMax`, `outputType`, `accuracy` (%
of full scale), `resolution?`, `responseTimeSec?`, `equipmentId`, `loopNumber?`,
`manufacturer`, `model`, `serialNumber`, `installDate`, `protectionClass`,
`processConnectionSize?`, `currentReading?`, `readingTimestamp?`, `isOnline`,
`alarmLow?`, `alarmHigh?`, `alarmLowLow?`, `alarmHighHigh?`, `calibration?`
(`SensorCalibration`: `calibratedAt`, `calibratedBy`, `nextCalibrationDue`,
`uncertaintyPct`, `certificateRef`), `scadaTagAddress?`.

#### 2.1.6 `Actuator`

`Actuator` represents an output device that drives a physical process element —
a motor, valve, heater, or relay. The `ActuatorType` union covers the 13
actuator classes most commonly found in industrial plants.

`ActuatorType` literal union (13 values): `ac_induction_motor`, `servo_motor`,
`stepper_motor`, `pneumatic_cylinder`, `hydraulic_cylinder`, `solenoid_valve`,
`proportional_valve`, `vfd_driven_motor`, `electric_actuator`,
`pneumatic_actuator`, `electric_heater`, `contactor`, `relay`.

`Actuator` fields: `actuatorId`, `tag`, `name`, `type`, `equipmentId`,
`controlOutputAddress`, `feedbackSensorId?`, `status` (`running`/`stopped`/
`faulted`/`maintenance`/`disabled`), `isOnline`, `manufacturer`, `model`,
`serialNumber`, `installDate`, one optional type-specific spec
(`motorSpec`/`pneumaticSpec`/`hydraulicSpec`/`vfdSpec`),
`currentCommandedValue?`, `currentFeedbackValue?`, `operatingHours`,
`startCount`. `MotorSpecification` carries `efficiencyClass` (`IE1`..`IE5`) and
`insulationClass` (`A`/`B`/`F`/`H`). `VFDSpecification.controlMode` is
`V/f`/`vector`/`direct_torque`.

#### 2.1.7 `PLC`

`PLC` represents a programmable logic controller — the device that runs the
control programs on a machine or production line. The `PLCVendor` and
`IEC61131Language` enums list the hardware vendors and programming languages
that Brigid recognizes.

`PLCVendor`: `siemens`, `allen_bradley`, `beckhoff`, `mitsubishi`, `omron`,
`schneider`, `delta`, `codesys`, `other`. `IEC61131Language`: `LD`, `ST`, `FBD`,
`IL`, `SFC`.

`PLC` fields: `plcId`, `tag`, `name`, `vendor`, `cpuModel`, `firmwareVersion`,
`rackAddress?`, `ipAddress?`, `cycleTimeMsec` (scan cycle), `memoryKB`,
`programs` (`PLCProgram[]`), `ioModules` (`PLCIOModule[]` — `ioType`
`DI`/`DO`/`AI`/`AO`/`mixed`), `commModules` (`PLCCommunicationModule[]`),
`equipmentId`, `isRedundant`, `isSafetyRated`, `silRating?`
(`SIL1`/`SIL2`/`SIL3`), `status` (`run`/`stop`/`fault`/ `maintenance`),
`cpuLoadPct?`, `diagnostics?`.

#### 2.1.8 `SCADASystem` / `SCADAPoint`

A SCADA system supervises the plant by collecting data from field devices and
presenting it to operators. `SCADAPoint` models each tag in the SCADA point
database — both the engineering configuration (range, alarms) and the live
values that update as the plant operates.

`SCADAPointType`: `AI`, `AO`, `DI`, `DO`, `calc`, `accumulator`.
`AlarmPriority`: `critical`, `high`, `medium`, `low`, `journal`.

`SCADAPoint` fields: `pointId`, `tag`, `description`, `pointType`,
`sourceAddress`, `engUnit`, `engRangeLow`, `engRangeHigh`, `deadband?`, `alarms`
(object with optional `hiHi`/`hi`/`lo`/`loLo`/`devHi`/`devLo`, each
`{ setpoint, priority, message }`), `historianEnabled`, `samplingRateSec`,
`currentValue?` (number|boolean), `quality?` (`good`/`bad`/`uncertain`),
`lastUpdated?`.

`SCADASystem` fields: `scadaId`, `name`, `vendor`, `version`, `topology`
(`standalone`/`client_server`/`redundant`/`distributed_node`), `serverNodes`
(each `{ nodeId, role, ipAddress }`, role `primary`/
`secondary`/`client`/`historian`), `totalPointCount`, `activeAlarmCount?`,
`pointDatabase` (`SCADAPoint[]`), `communicationDrivers`, `redundancyEnabled`,
`historianRetentionDays`, `isOnline`, `lastBackupDate?`.

#### 2.1.9 `HMITerminal` / `HMIScreen` / `HMIDisplayObject`

The HMI types model an operator interface terminal, the screens it displays, and
the individual display objects on each screen. The ISA-101 hierarchy
(`L1_overview` through `L5_diagnostic`) governs which level of detail each
screen presents, and the numeric `accessLevel` (0=view through 4=admin) controls
who can interact with each screen.

`HMIDisplayObjectType` (12 values): `numeric_display`, `text_display`,
`bar_graph`, `trend_chart`, `alarm_banner`, `status_indicator`, `pushbutton`,
`slider`, `dropdown`, `faceplate`, `image`, `animation`. `HMIScreen.level` is
the ISA-101 hierarchy `L1_overview`, `L2_area`, `L3_detail`, `L4_faceplate`,
`L5_diagnostic`; `accessLevel` is a numeric ladder 0=view, 1=operator,
2=supervisor, 3=engineer, 4=admin.

#### 2.1.10 `ControlLoop`

A control loop ties a sensor (the process variable) to an actuator (the
manipulated variable) through a control strategy. `ControlLoopStrategy`
enumerates the available strategies from simple PID through model-predictive
control, and `PIDParameters` holds the tuning values needed to implement them.

`ControlLoopStrategy`: `PID`, `cascade`, `feedforward`, `ratio`, `split_range`,
`override_select`, `MPC`, `fuzzy_logic`, `adaptive`. `PIDParameters` carries
`proportionalGain` (Kp), `integralTimeSec` (Ti), `derivativeTimeSec` (Td),
`filterTimeSec?`, `deadband?`, `outputMin`, `outputMax`, `reverse`.
`ControlLoop.mode` is `auto`/`manual`/`cascade`/ `computer`/`out_of_service`;
`tuningStatus` is `not_tuned`/`initial`/ `optimal`/`needs_retuning`.

#### 2.1.11 `ProductionLine` / `WorkStation`

`WorkStation` fields: `stationId`, `name`, `sequenceNumber`,
`processingTimeSec`, `setupTimeSec`, `machineId?`, `operatorCount`,
`bufferInCapacity`, `bufferOutCapacity`, `isBottleneck`, `scrapRatePct`,
`automationLevel` (`manual`/`semi_auto`/`fully_auto`).

`ProductionLine` fields: `lineId`, `name`, `description`, `factoryId`, `areaId`,
`stations` (`WorkStation[]`), `taktTimeSec`, `targetThroughputPerHr`,
`actualThroughputPerHr?`, `lineLengthM`, `productFamilies`, `shiftHoursPerDay`,
`shiftsPerDay`, `workingDaysPerYear`, `annualCapacityUnits`, `oee?`, `status`,
`currentJobOrder?`. `ProductionLine.status` literal union: `running`,
`scheduled_downtime`, `unplanned_downtime`, `changeover`, `idle`.

#### 2.1.12 `Factory` / `FactoryArea`

`FactoryArea` carries `cleanroomClass?` (`ISO5`..`ISO8`) and `hazardousArea`.
`Factory` fields include `siteCode`, `address`, `country`, `region`,
`coordinates?`, area breakdown (`totalFloorAreaM2`, `coveredAreaM2`,
`openAreaM2`), `headcount`, `areas`, `productionLineIds`, `utilitySystems`
(power supply, backup generator, solar installed kWp, battery storage kWh,
compressed air, chiller tonnage, boiler, water supply, effluent treatment),
`certifications`, `status` (`operational`/`ramp_up`/`shutdown`/`construction`).

#### 2.1.13 `IndustrialNetwork`

`IndustrialProtocolType` literal union (21 values): `PROFINET`, `EtherCAT`,
`EtherNet_IP`, `Modbus_TCP`, `Modbus_RTU`, `DeviceNet`, `CANopen`,
`PROFIBUS_DP`, `PROFIBUS_PA`, `CC_Link`, `AS_Interface`, `IO_Link`, `HART`,
`Foundation_Fieldbus`, `OPC_UA`, `MQTT`, `Modbus_ASCII`, `DNP3`,
`IEC_60870_5_101`, `IEC_60870_5_104`, `IEC_61850`.

`IndustrialNetwork` fields: `networkId`, `name`, `protocol`, `topology`
(`star`/`ring`/`line`/`tree`/`mesh`), `mediaType` (`copper_ethernet`/
`fiber`/`coaxial`/`twisted_pair`/`wireless`), `bandwidth`, `maxDevices`, `nodes`
(`NetworkNode[]`), `isRedundant`, `managedSwitch`, `vlanId?`, `segmentation`
(`isolated_OT`/`DMZ`/`converged_IT_OT`/`air_gapped`), `latencyUsec?`,
`cycleTimeMsec?`.

#### 2.1.14 `SafetySystem` / `SafetyInstrumentedFunction`

Safety-instrumented systems are the last line of defense before a hazard becomes
an incident. `SafetyInstrumentedFunction` models a specific protective function
— for example "shut the feed valve if reactor pressure exceeds 15 bar" — with
its SIL target, probability of failure on demand, and the voting logic that
decides when to act. `SafetySystem` groups these functions under a named system
and records the fail-safe actions and bypass procedures that the
deterministic-fallback requirement (§9.1) depends on.

`SILRating`: `SIL1`..`SIL4`. `PerformanceLevel`: `PLa`..`PLe`.
`SafetyFunctionCategory`: `Cat_B`, `Cat_1`..`Cat_4`.

`SafetyInstrumentedFunction` fields: `sifId`, `description`, `silTarget`,
`silAchieved?`, `pfdAvg` (probability of failure on demand),
`riskReductionFactor` (1/PFDavg), `initiators` (each `{ tagId, voteLogic }`,
e.g. `2oo3`), `finalElements` (each `{ tagId, failSafePosition }` —
`open`/`closed`/`de_energised`), `logicSolver`, `proofTestIntervalMonths`,
`partialStrokeTestEnabled`, `lastProofTestDate?`, `diagnosticCoverage` (0–1).

`SafetySystem.standard`: `IEC_61511`, `IEC_61508`, `ISO_13849`, `IEC_62061`.
`safeguardType`: `emergency_shutdown`, `burner_management`, `fire_and_gas`,
`machine_guarding`, `pressure_protection`, `high_integrity_pressure`.
`SafetySystem.failSafeAction` is the recorded deterministic fail-safe action and
`bypassProcedure` the recorded bypass/inhibit procedure; `inhibitCount` tracks
active bypasses.

### 2.2 Maintenance & Calibration Types (`maintenance.ts`)

This module defines the work-order, calibration, and spare-parts models. Work
orders are the unit of action for all maintenance activity; calibration records
are ISO 17025 compliance objects with strict immutability rules; spare parts
carry the stock and reorder parameters that drive inventory management.

#### 2.2.1 `MaintenanceRecord` (work order)

`MaintenanceType` literal union (8 values): `corrective`,
`preventive_scheduled`, `preventive_condition_based`, `predictive`,
`improvement`, `inspection`, `overhaul`, `statutory`.

`WorkOrderStatus` literal union (13 values): `draft`, `submitted`, `approved`,
`parts_ordered`, `scheduled`, `assigned`, `in_progress`, `pending_parts`,
`pending_approval`, `completed`, `verified`, `closed`, `cancelled`. The
canonical work-order lifecycle therefore runs
`draft → submitted → approved → parts_ordered → scheduled → assigned → in_progress → (pending_parts | pending_approval) → completed → verified → closed`,
with `cancelled` reachable as a terminal state. `closed` and `cancelled` are
terminal. (The `@brigid/db` enum `brigid_work_order_status` is the same set
minus `pending_approval` — see §3.1.)

`MaintenancePriority`: `emergency`, `urgent`, `high`, `medium`, `low`,
`scheduled`.

`MaintenanceRecord` fields: `workOrderId`, `title`, `description`,
`maintenanceType`, `priority`, `status`, `equipmentId`, `equipmentName`,
`location`, lifecycle timestamps (`requestedAt`, `requestedBy`, `approvedAt?`,
`approvedBy?`, `scheduledStart?`, `scheduledEnd?`, `actualStart?`, `actualEnd?`,
`closedAt?`, `closedBy?`), failure information (`failureMode?`, `failureCause?`,
`failureEffect?`, `symptomDescription?`, `downTimeHours`), `workPerformed?`,
`laborEntries` (`LaborEntry[]` — technician, trade, start/end, hours, hourly
rate GHS, total cost GHS), `materialsUsed` (`MaterialUsed[]` — spare part, part
number, quantity, unit and total cost GHS), cost summary (`totalLaborCostGHS`,
`totalMaterialCostGHS`, `totalCostGHS`), post-maintenance check
(`functionalTestPassed?`, `operatorSignOff?`, `verifiedBy?`,
`rootCauseAnalysis?`, `correctiveActions?`, `preventiveActionsRecommended?`),
`attachments` (`{ type, url, description }[]`).

#### 2.2.2 `CalibrationRecord`

A calibration record documents that an instrument was compared to a traceable
reference standard on a specific date, with the as-found and as-left readings
and the expanded measurement uncertainty calculated per the GUM. Once signed
off, this record is immutable — any subsequent correction creates a new
append-only entry rather than modifying the original.

The core measurement object is the `CalibrationPoint`: `nominalValue`,
`referenceValue`, `measuredValue`, `error` (measured − reference), `uncertainty`
(expanded, k=2, 95%), `withinTolerance`.

`CalibrationRecord` fields: `calibrationId`, `instrumentId`, `instrumentTag`,
`instrumentDescription`, `calibrationDate`, `calibrationDue`,
`calibrationInterval` (months), `calibrationProcedure`, `labReference?`,
`calibratorName`, `supervisorName`, `location`, `ambientTemperatureC`,
`relativeHumidityPct`, `referenceStandard`
(`{ description, serialNumber, calibrationCertRef, calibratedBy, calibrationDate, traceabilityChain }`
— traceability chain e.g. `BIPM > NPL > GNAS > Lab`), `measurementPoints`
(`CalibrationPoint[]`), `expandedUncertainty`, `uncertaintyUnit`,
`asFoundStatus` (`within_tolerance`/`out_of_tolerance`/`not_assessed`),
`asLeftStatus` (`within_tolerance`/`adjusted`/`failed`), `adjustmentMade`,
`adjustmentDescription?`, `certificateNumber`, `certificateIssuedAt`, `result`
(`pass`/`fail`/`conditional_pass`), `notes?`.

#### 2.2.3 `SparePart`

`SparePart` tracks a stocked component that may be needed to repair equipment.
The `SparePartCriticality` ABC classification (A=critical, B=essential,
C=general) drives the stocking strategy and reorder rules.

`SparePartCriticality`: `critical_A`, `essential_B`, `general_C`.
`StockingStrategy`: `min_max`, `reorder_point`, `consignment`, `on_demand`,
`insurance`.

`SparePart` fields: `sparePartId`, `partNumber`, `oemPartNumber?`,
`description`, `manufacturer`, `equipmentCompatibility` (`string[]` of equipment
IDs the part fits), `category`, `criticality`, `stockingStrategy`,
`currentStockQty`, `minStockQty`, `maxStockQty`, `reorderPoint`, `reorderQty`,
`leadTimeDays`, `unitCostGHS`, `totalStockValueGHS`, `storageLocation`,
`unitOfMeasure`, `shelfLifeMonths?`, `warrantyMonths?`, `lastOrderDate?`,
`lastUsedDate?`, `annualUsageQty`, `interchangeableParts`
(`SparePartInterchangeability[]`), `suppliers` (each
`{ supplierId, supplierPartNumber, leadTimeDays, unitCostGHS }`), `notes?`.

#### 2.2.4 `FailureMode` / `FMEAEntry`

A Failure Mode and Effects Analysis (FMEA) entry documents how a specific
component can fail, the effect of that failure, and the Risk Priority Number
(RPN = Severity × Occurrence × Detection) that ranks it for action. The
`FailureModeDetectionMethod` enum lists the nine methods by which a failure mode
can be detected before or after it occurs.

`FailureModeDetectionMethod` (9 values): `visual_inspection`,
`vibration_analysis`, `thermal_imaging`, `oil_analysis`, `ultrasonic`,
`process_parameter`, `periodic_test`, `alarm_trip`, `continuous_monitoring`.

`FMEAEntry` columns: `fmeaId`, `equipmentId`, `component`, `function`,
`failureMode`, `failureEffect`, `failureCause`, `localEffect`, `systemEffect`,
`severity` (1–10), `occurrence` (1–10), `detection` (1–10), `rpn` (Risk Priority
Number = S×O×D), `detectionMethod`, `currentControls`, `recommendedAction`,
`responsiblePerson?`, `targetDate?`, `actionTaken?`, and revised values
(`revisedSeverity?`, `revisedOccurrence?`, `revisedDetection?`, `revisedRPN?`).

#### 2.2.5 `ConditionIndicator` (predictive maintenance)

A `ConditionIndicator` tracks one health parameter for one equipment component
over time. It stores the baseline value, live readings, the current trend, and
the thresholds that trigger alerts and alarms. The `ConditionParameterType` enum
covers 16 measurable health indicators drawn from vibration analysis, oil
analysis, thermal imaging, and electrical monitoring disciplines.

`ConditionParameterType` (16 values): `vibration_rms`, `vibration_peak`,
`vibration_spectrum_band`, `bearing_temperature`, `winding_temperature`,
`oil_viscosity`, `oil_metal_content_ppm`, `oil_water_content_pct`,
`motor_current_rms`, `motor_current_spectrum`, `ultrasonic_db`,
`thermal_hotspot_C`, `pressure_drop_bar`, `flow_deviation_pct`,
`efficiency_pct`, `noise_dB`.

`ConditionTrend`: `stable`, `improving`, `gradual_deterioration`,
`rapid_deterioration`, `critical`.

`ConditionThreshold` has `alertLevel`, `alarmLevel`, `dangerLevel`, `unit`, and
optional `isoZone` (ISO 10816-3 vibration severity zone `A`/`B`/`C`/`D`).
`ConditionIndicator` fields: `indicatorId`, `equipmentId`, `componentName`,
`parameterType`, `thresholds`, `baselineValue`, `baselineMeasuredAt`,
`latestValue?`, `latestMeasuredAt?`, `trend`, `remainingUsefulLifePct?` (0–100),
`predictedFailureDate?`, `readings` (`ConditionReading[]`),
`monitoringFrequency` (`continuous`/`daily`/`weekly`/`monthly`/ `quarterly`),
`alertActive`, `alarmActive`.

#### 2.2.6 `MaintenanceSchedule`

A `MaintenanceSchedule` aggregates all the planned maintenance jobs for a
facility and reports summary metrics (overdue count, compliance percentage).
Each job is driven by a `MaintenanceTrigger` that fires on one of five trigger
types — time, run-hours, cycles, condition threshold, or external event.

`ScheduleTriggerType`: `calendar`, `running_hours`, `cycle_count`, `condition`,
`event`. A `MaintenanceTrigger` carries the parameters for its trigger type
(interval days / day-of-week / day-of-month / month-of-year for calendar;
interval hours and current reading for running hours; interval cycles and
current count for cycle count; `conditionIndicatorId` plus
`conditionThresholdType` `alert`/`alarm`/`danger` for condition;
`triggeringEvent` for event).

`MaintenanceTask` carries `permitToWorkRequired` and `permitType`
(`hot_work`/`confined_space`/`electrical_isolation`/`general`),
`isolationRequired`, plus tools and required parts. `ScheduledMaintenanceJob`
links to a generated `latestWorkOrderId` and tracks `isOverdue` / `nextDueAt`.
`MaintenanceSchedule` aggregates jobs and reports `overdueJobCount`,
`dueTodayCount`, `dueThisWeekCount`, `plannedMaintenanceHrPerMonth`,
`maintenanceCompliancePct` (on-time completion rate).

### 2.3 Energy & Utility Types (`energy.ts`)

This module models energy generation, storage, and consumption for industrial
sites. The types are deliberately optimized for West African operating
conditions: Ghana ECG tariff structures, high-solar-irradiance array
configurations, grid-reliability fields for sites that experience frequent
outages, and diesel-hybridization logic for backup generation. The module also
covers water treatment plants and refrigeration systems, since both are utility
systems that appear as energy consumers in industrial site energy models.

#### 2.3.1 `EnergySystem`

`EnergySourceType`: `solar_pv`, `battery_storage`, `grid`, `diesel_generator`,
`wind`, `biogas`, `hydro`. `LoadPriority`: `critical`, `essential`, `normal`,
`deferrable`, `interruptible`.

`EnergySystem.operatingMode` literal union: `grid_only`, `solar_grid`,
`solar_battery_grid`, `island_mode`, `diesel_backup`, `full_renewable`.
`controllerType`: `manual`, `automatic`, `microgrid_controller`, `EMS`. The
record carries `sources` (`EnergySourceMix[]`), `loads` (`EnergyLoad[]`),
capacity and load aggregates, grid-connection flags, asset references
(`batteryBankId?`, `dieselGeneratorId?`, `solarArrayId?`,
`automaticTransferSwitchId?`), tariff fields, and Ghana ECG reliability fields
`gridOutagesPerMonth?` and `avgOutageDurationHr?`.

#### 2.3.2 `SolarArray`

`SolarPanelTechnology`: `monocrystalline`, `polycrystalline`, `thin_film_CdTe`,
`thin_film_CIGS`, `bifacial`, `HIT`. `SolarPanel` carries electrical
characteristics (`ratedPowerWp` at STC, `vocV`, `vmpV`, `iscA`, `impA`,
`tempCoefficientPmaxPctPerC`, `noctC`, `degradationRateYrPct`). `SolarArray`
carries `panel`, `strings` (`StringConfiguration[]`), `inverters`
(`SolarInverter[]` — type `string`/`central`/`microinverter`/ `hybrid`),
`tiltAngleDeg`, `azimuthDeg`, `mountingType` (`rooftop_fixed`/
`ground_fixed`/`ground_tracking_1axis`/`ground_tracking_2axis`/`carport`), loss
factors (`shadingFactorPct`, `dirtSoilingLossPct`, `cablingLossPct`),
`averageDailySunHrs`, `estimatedAnnualYieldKWh`, `performanceRatioPct`, and live
readings (`currentOutputKW?`, `todayYieldKWh?`, `lifetimeYieldKWh?`).

#### 2.3.3 `BatteryBank`

`BatteryChemistry` (8 values): `lithium_ion_NMC`, `lithium_iron_phosphate_LFP`,
`lead_acid_flooded`, `lead_acid_AGM`, `lead_acid_VRLA`, `vanadium_flow`,
`zinc_bromine_flow`, `sodium_ion`. `BatteryTopology`: `AC_coupled`,
`DC_coupled`, `hybrid_inverter_integrated`.

`BatteryBank` carries nominal/usable capacity, `depthOfDischargePct`,
charge/discharge power limits, `roundTripEfficiencyPct`, `cycleLifeAt80PctDoD`,
`calendarLifeYears`, and live state (`stateOfChargePct?` SOC,
`stateOfHealthPct?` SOH, `stateOfFunctionPct?`, power and voltage readings,
`temperatureC?`, `totalCyclesCompleted?`, `lifetimeEnergyThroughputKWh?`,
`alarms?`).

#### 2.3.4 `PowerManagementSystem`

`SourceSwitchLogic` (7 values): `solar_first_battery_backup_grid_last`,
`solar_first_grid_backup`, `grid_first_solar_supplement`, `peak_shaving_mode`,
`off_peak_charge_mode`, `time_of_use_optimized`, `custom`. A `LoadSheddingRule`
ties a `LoadPriority` group to `shedAtBatterySocPct` and
`restoreAtBatterySocPct`. `PowerManagementSystem` carries the switch logic,
load-shedding rules, grid-charge / solar-export setpoints, Ghana ECG peak /
off-peak tariffs and demand charge, and live readings (`currentMode?`
`solar`/`battery`/`grid`/`hybrid`/`diesel`, import/ export/solar/battery/load
power, `alarms?`).

#### 2.3.5 `WaterTreatmentPlant`

`TreatmentProcessStage` is a 20-value literal union covering the full treatment
train (`intake_screening`, `coagulation`, `flocculation`, `sedimentation`,
`dissolved_air_flotation`, `rapid_sand_filtration`, `slow_sand_filtration`,
`activated_carbon_filtration`, `membrane_ultrafiltration`, `reverse_osmosis`,
`nanofiltration`, `chlorination`, `UV_disinfection`, `ozonation`,
`pH_correction`, `softening`, `fluoridation`, `sludge_thickening`,
`sludge_dewatering`, `effluent_discharge`). `WaterTreatmentPlant` carries
`plantType`, `sourceWaterType`, `treatmentTrain` (`TreatmentStage[]`),
`waterQualityTargets` (`WaterQualityTarget[]` referencing standards such as
`WHO 2022`, `Ghana EPA WQ Standards`, `Ghana-WS 175`), `regulatoryAuthority`,
permit fields, and `currentStatus`
(`operating`/`reduced_capacity`/`maintenance`/`shutdown`/`emergency`).

#### 2.3.6 `RefrigerationSystem`

`Refrigerant` is a 12-value literal union with documented GWP (`R134a`, `R404A`,
`R407C`, `R410A`, `R744`, `R717`, `R290`, `R600a`, `R1234yf`, `R1234ze`,
`R448A`, `R449A`). `RefrigerationSystemType` (7 values):
`vapour_compression_direct_expansion`, `vapour_compression_flooded`, `cascade`,
`absorption`, `transcritical_CO2`, `ammonia_industrial`, `secondary_coolant`.
`RefrigerationSystem` carries `cop` (cooling capacity / power input),
`eer?`/`seer?`, temperature setpoints, `components`
(`RefrigerationComponent[]`), `application` (8 values incl.
`pharmaceutical_cold_chain`), F-gas compliance fields, and `currentStatus`
(`running`/`standby`/`maintenance`/`fault`/`defrost`).

### 2.4 Robotics & Digital Twin Types (`robotics.ts`)

This module models robots, robot cells, digital twins, automated guided
vehicles, and grippers. The safety-zone types are especially important: they
define the ISO/TS 15066 spatial regions around a robot cell and enforce the
conditions under which humans can be present.

#### 2.4.1 `Robot`

`RobotType` (8 values): `articulated_6dof`, `articulated_7dof`, `SCARA`,
`delta_parallel`, `cartesian_gantry`, `collaborative_cobot`, `dual_arm`,
`mobile_robot_arm`. `RobotSafeguardingType` (7 values): `hard_guarding`,
`light_curtain`, `safety_laser_scanner`, `safety_mat`,
`speed_and_separation_monitoring`, `power_and_force_limiting`, `hand_guiding`.

`RobotKinematic` carries `dof`, per-joint ranges, `reachMm`, `repeatabilityMm`
(ISO 9283), `maxToolCentrePointSpeedMPerSec`, `maxPayloadKg`,
`nominalPayloadKg`. `Robot` adds `vendor`, `model`, `controllerModel`,
`programmingLanguage`, `ros2Compatible`, `cellId?`, `gripperId?`,
`visionSystemId?`, `operatingHours`, `cycleCount`, `safeguardingType`,
`safetyValidated` (ISO 10218-2 / ISO/TS 15066), `lastSafetyValidationDate?`.
`Robot.status` literal union: `running`, `idle`, `paused`, `manual_mode`,
`fault`, `e_stopped`, `maintenance`.

#### 2.4.2 `RobotCell` / `SafetyZone`

`SafetyZoneType` (5 values): `collaborative_space` (ISO/TS 15066 SSM),
`restricted_space`, `safeguarded_space`, `operating_space`, `maximum_space`.
`SafetyZone` carries `zoneType`, optional GeoJSON polygon boundary,
`monitoringDevice?`, `allowedHumanPresence`, `entryProcedure?`,
`minHumanApproachSpeedMPerSec?`. `RobotCell` aggregates `robots`, `safetyZones`,
`applications`, vision systems, PLC/HMI references, and risk-assessment metadata
(`riskAssessmentRef?`, `riskAssessmentDate?`, `riskAssessmentRevision?`,
`safetyFunctionIds`).

#### 2.4.3 `DigitalTwin`

`TwinFidelity` (5 values): `geometry_only`, `kinematic`, `physics_based`,
`data_driven`, `hybrid_physics_data`. `DigitalTwin.assetType`: `machine`,
`robot_cell`, `production_line`, `factory`, `energy_system`, `process`.
`geometryFormat?`: `STEP`, `IFC`, `glTF`, `FBX`, `URDF`, `OBJ`.
`simulationEngine?`: `MATLAB_Simulink`, `ANSYS_Twin_Builder`, `Dymola`,
`OpenModelica`, `custom`. The twin carries `dataBindings` (`TwinDataBinding[]` —
each maps a `twinAttributePath` to a `scadaTagId` with `pollingRateMs` and
optional transform), `currentSimulations` (`TwinSimulationState[]`), `kpis`,
sync metadata (`lastSyncedAt?`, `syncLatencyMs?`, `isRealTimeEnabled`).

#### 2.4.4 `AGV`

`AGVNavigationType` (7 values): `magnetic_tape`, `wire_guidance`,
`reflector_laser`, `natural_feature_lidar`, `SLAM`, `QR_code`, `vision_based`.
`AGVType`: `tugger`, `unit_load`, `forklift_AGV`, `AMR_mobile_robot`,
`overhead_AGV`. `AGV.status` literal union: `idle`, `in_mission`, `charging`,
`waiting`, `blocked`, `fault`, `e_stopped`. `safetyStandard`: `ISO_3691-4`,
`ANSI_B56.5`, `other`.

#### 2.4.5 `Gripper`

`GripperPrinciple` (10 values): `vacuum_suction`, `pneumatic_parallel_jaw`,
`pneumatic_3_finger`, `servo_electric_parallel`, `servo_electric_adaptive`,
`magnetic_permanent`, `magnetic_electro`, `soft_pneumatic`, `needle_gripper`,
`bernoulli`. `Gripper` carries `capability` (`GripperPayloadCapability`),
`mountType` (`ISO_9409_1`/`proprietary`), tool-changer compatibility,
`sensingCapability?` (`none`/`touch`/ `force_torque`/`vision`),
`robotCompatibility`.

#### 2.4.6 `SimulationScenario`

`SimulationEngine` (7 values): `DES`, `FEA`, `CFD`, `MBS`, `co_simulation`,
`agent_based`, `monte_carlo`. A scenario carries `parameters`
(`SimulationParameter[]` with `baselineValue` and `testValues` to sweep),
`kpiTargets` (each with `direction` `maximize`/`minimize`/ `target`), `runs`
(`SimulationResult[]`), `baselineRunId?`, `recommendedRunId?`, `status`
(`draft`/`running`/`completed`/`failed`).

### 2.5 Security & Training Types (`security.ts`)

This module defines the OT cybersecurity and workforce training types. The
security types model threats, assessments, zones, conduits, and vulnerabilities
per the IEC 62443 framework; the training types model programs, competency
units, and certifications aligned to the Ghana NQF and Bloom's taxonomy.

#### 2.5.1 `CyberThreat`

`OTThreatCategory` (14 values): `ransomware`, `supply_chain_compromise`,
`insider_threat`, `APT_nation_state`, `protocol_exploitation`,
`firmware_attack`, `man_in_the_middle`, `denial_of_service`, `credential_theft`,
`physical_cyber_attack`, `engineering_workstation_compromise`,
`USB_removable_media`, `remote_access_abuse`, `third_party_vendor`.
`ThreatActorType` (6 values): `nation_state`, `criminal_organization`,
`hacktivist`, `insider`, `opportunist`, `competitor`. `ImpactDomain` (7 values):
`safety`, `reliability`, `quality`, `environment`, `financial`, `regulatory`,
`reputational`.

`CyberThreat` carries CVSS v3.1 fields (`cvssScore?`, `attackComplexity`
`low`/`high`, `privilegesRequired` `none`/`low`/`high`,
`userInteractionRequired`), `mitreTechniques` (`MITREATTCKTechnique[]` — ATT&CK
for ICS), `iec62443ThreatLevel` (`T1_basic`/`T2_enhanced`/
`T3_advanced`/`T4_sophisticated`), `probability` (`very_low`..`very_high`),
`residualRisk` (`low`/`medium`/`high`/`critical`), `safetyImplication`.

#### 2.5.2 `SecurityAssessment` / `SecurityZone` / `SecurityConduit`

`IEC62443SecurityLevel`: `SL0`..`SL4`. `SecurityZoneType` (6 values):
`enterprise`, `DMZ`, `supervisory`, `control`, `field_device`, `safety`.
`SecurityZone` carries `targetSecurityLevel` and `achievedSecurityLevel?` (IEC
62443-3-2). `SecurityConduit` declares allowed cross-zone communication,
protocols, encryption and authentication requirements. `VulnerabilityFinding`
carries `severity` (`critical`/`high`/`medium`/ `low`/`informational`),
`cveId?`, `cvssScore?`, `remediationStatus`
(`open`/`in_progress`/`resolved`/`risk_accepted`).
`SecurityAssessment.standard`: `IEC_62443`, `NIST_CSF`, `ICS_CERT`, `ISA_99`,
`NERC_CIP`. `assessmentType`: `gap_analysis`, `vulnerability_assessment`,
`penetration_test`, `compliance_audit`, `risk_assessment`. `status`:
`planned`/`in_progress`/`completed`/ `remediation`. The record rolls up
`maturityLevel?` (0–4), `overallSecurityScore?` (0–100), and finding counts by
severity.

#### 2.5.3 `IndustrialProtocol`

A protocol reference object with `dataModel` (`tag_value`/`object_model`/
`register_map`/`message_based`/`publish_subscribe`), `securitySupport`
(`none`/`signing_only`/`signing_and_encryption`/`full_PKI`),
`knownVulnerabilities`, conformance/certification metadata, and `safetyProfile?`
(e.g. `PROFIsafe`, `FSoE`, `CIP Safety`).

#### 2.5.4 `TrainingProgram` / `TrainingModule` / `CompetencyUnit`

`CompetencyLevel`: `awareness`, `working`, `practitioner`, `expert`.
`LearningModality` (6 values): `classroom`, `online_elearning`, `hands_on_lab`,
`simulation`, `on_the_job`, `mentorship`. `CompetencyUnit` separates
`knowledgeElements` (K), `skillElements` (S), `attitudeElements` (A) outcomes
with `assessmentCriteria` and `assessmentMethod`
(`written_test`/`practical_demonstration`/`portfolio`/ `observation`/`project`).
`TrainingProgram` carries `modules`, `accreditationBody?`, `nqfLevel?` (Ghana
NQF 1–10), `costPerTraineeGHS`, `batchCapacity`, `employmentOutcomes`.

#### 2.5.5 `Certification`

`CertificateStatus`: `active`, `expired`, `suspended`, `revoked`,
`pending_renewal`. `Certification` carries `holderId`, `holderType`
(`individual`/`organization`), `certificateNumber`, `programId?`, `issuingBody`,
`standard?`, `scope`, `issuedDate`, `expiryDate`, `renewalWindowDays`
(notify-before-expiry window), `competencyUnitsAchieved`, `auditHistory`
(`CertificationAuditEntry[]` — audit type
`initial`/`surveillance`/`renewal`/`special`, with major/minor
non-conformances), `cpd` (continuing-professional-development entries),
`suspensionReason?`, `revocationReason?`.

### 2.6 Business & Financial Types (`business.ts`)

This module defines the commercial and production-management types: BOMs,
project estimates, production orders, quality records, supply-chain nodes, and
market intelligence reports. These types sit at the boundary between Brigid's
operational data and the financial and analytical data that Maat and
`@brigid/financials` consume.

#### 2.6.1 `BillOfMaterials` / `BOMItem`

`BOMType`: `engineering`, `manufacturing`, `service`, `phantom`, `planning`.
`BOMItemType`: `purchased`, `manufactured`, `sub_contracted`, `configured`,
`phantom`. `BOMItem` is recursive (`childItems: BOMItem[]`), carrying `level`,
`partNumber`, `revision`, `quantity`, `wasteFactorPct?`, effectivity dates, cost
fields and `criticalItem`. `BillOfMaterials.status`: `draft`, `in_review`,
`approved`, `released`, `obsolete`.

#### 2.6.2 `ProjectEstimate` / `CostLineItem`

`ProjectPhase` (11 values): `concept`, `feasibility`, `front_end_engineering`,
`detailed_engineering`, `procurement`, `manufacturing`, `installation`,
`commissioning`, `training`, `handover`, `warranty`. `CostLineItem.category` is
a 12-value union (`materials`, `equipment`, `labour_engineering`,
`labour_installation`, `labour_commissioning`, `procurement`,
`transport_logistics`, `third_party_vendors`, `contingency`, `overhead`,
`warranty`, `training`). `ProjectEstimate.estimateClass` is the AACE-style
ladder `Class5_ROM`/`Class4_Screening`/`Class3_AFCE`/`Class2_Control`/
`Class1_Check`. The record rolls up cost categories, contingency and overhead
percentages, `quotedPriceGHS?`, and `grossMarginGHS?`.

#### 2.6.3 `ProductionOrder` / `ProductionOperation`

`ProductionOrderStatus` (8 values): `planned`, `released`, `dispatched`,
`executing`, `paused`, `completed`, `closed`, `cancelled`.
`ProductionOperation.status`: `not_started`, `in_progress`, `completed`,
`skipped`. `ProductionOrder` carries `bomId`, `routingId?`, `quantity`,
`operations` (`ProductionOperation[]`), `issuedMaterials`, `quantityCompleted`,
`quantityRejected`, `firstPassYieldPct?`, batch and serial traceability.
Invariant (`ProductionOrderSchema`): `plannedEndDate` must be on or after
`plannedStartDate`.

#### 2.6.4 `QualityRecord` / `SPCControlChart` / `NonConformanceReport`

`ControlChartType` (9 values): `Xbar_R`, `Xbar_S`, `I_MR`, `p_chart`,
`np_chart`, `c_chart`, `u_chart`, `CUSUM`, `EWMA`. `SPCControlChart` carries
Shewhart limits (`ucl`, `lcl`, `clCentreLine`), capability indices (`cp`, `cpk`,
`pp`, `ppk`, `sigma`), out-of-control `signals`, and `measurements`.
`QualityRecord.inspectionType`: `incoming`, `in_process`, `final`, `audit`,
`destructive_test`; `inspectionLevel`: AQL `S1`..`S4` or `100%`;
`overallResult`: `pass`/`fail`/`conditional_pass`/`hold`.
`NonConformanceReport.disposition`: `rework`, `scrap`, `use_as_is`,
`return_to_supplier`, `pending`; `severity`: `critical`/`major`/`minor`/
`cosmetic`.

#### 2.6.5 `SupplyChainNode`

`SupplyChainNodeType` (10 values): `raw_material_supplier`,
`component_supplier`, `sub_assembly_supplier`, `contract_manufacturer`,
`warehouse_distribution`, `factory`, `regional_distribution_centre`, `customer`,
`port_clearance`, `3PL_logistics`. The node carries performance KPIs,
inbound/outbound logistics connections (`transportMode`
`road`/`sea`/`air`/`rail`), `inventory` (`SupplyChainInventory[]`), resilience
flags (`singleSourceRisk`, `countryRiskLevel?`), and `activeStatus`
(`active`/`approved_not_used`/`probationary`/`suspended`/ `disqualified`).

#### 2.6.6 `MarketIntelligenceReport`

The report carries TAM/SAM/SOM (`totalAddressableMarketGHS`,
`serviceableAddressableMarketGHS`, `serviceableObtainableMarketGHS`),
`marketMaturity` (`emerging`/`growing`/`mature`/`declining`), `segments`,
`competitors`, an optional Porter's Five Forces block (each force
`low`/`medium`/`high`), and `recommendedStrategyActions`.

### 2.7 Unit Conversion Library (`units.ts`)

Industrial data arrives in a wide variety of engineering units — bar or psi,
Celsius or Fahrenheit, m³/hr or GPM. This library provides typed conversion
functions so all downstream logic works in consistent SI units. Each function
converts through the SI base unit, preventing the accumulation of rounding
errors across multi-step conversions.

Provided converters: `convertPressure`, `convertTemperature` (C/F/K/R),
`convertVolumetricFlow`, `convertMassFlow`, `convertEnergy`, `convertPower`,
`convertLength`, `convertArea`, `convertMass`, `convertSpeed`, `convertTorque`,
`convertElectricalCurrent`, `convertAngle`, `convertAngularSpeed`,
`convertVolume`, `convertDynamicViscosity`. The `UnitCategory` type enumerates
27 categories.

OEE/production helpers: `minutesToHours`, `hoursToMinutes`, `secondsToMinutes`,
`cycleTimeToThroughput`, `throughputToCycleTime`, `calculateTaktTime`.

Ghana energy: `GhanaECGTariffs` (constant — LV/HV industrial GHS/kWh, demand
charge GHS/kVA/month, fixed monthly charge) and
`calculateMonthlyElectricityBillGHS(energyKWh, peakDemandKVA, voltageLevel)`
which returns `{ energyCostGHS, demandCostGHS, fixedCostGHS, totalGHS }`.

### 2.8 Engineering & Data-Quality Validators (`validators.ts`)

This module provides two categories of validator: engineering calculation
validators that check the physics of a design, and data-quality validators that
flag suspect readings in a live sensor stream. Both return structured results
rather than throwing exceptions, so callers can surface warnings and errors to
operators rather than silently discarding data.

#### 2.8.1 Engineering calculation validators

Each returns a `ValidationResult`
(`{ valid, warnings, errors, calculatedValues }`):

- `validatePressureDrop` — Darcy-Weisbach pipe pressure drop; computes Reynolds
  number, friction factor (laminar `64/Re`; Blasius in transition; Haaland
  approximation to Colebrook-White in turbulent flow), pressure drop, velocity
  head.
- `validateHeatTransfer` — counter-current LMTD heat-exchanger duty
  (`Q = U·A·LMTD`); rejects physically impossible temperature profiles.
- `validateElectricalLoad` — three-phase motor load check; full-load current,
  load factor, apparent/active/reactive power, voltage-imbalance and
  power-factor warnings.
- `validateStructuralStress` — axial stress `σ = F/A` against allowable stress
  (yield / safety factor, default factor 2.5).

#### 2.8.2 Industrial data-quality validators

`DataQualityStatus`: `good`, `suspect`, `bad`. Each returns a
`DataQualityResult` (`{ status, flags, filteredValue? }`):

- `checkSensorRange` — value vs engineered range and EU range.
- `checkRateOfChange` — flags changes faster than physically plausible.
- `checkStuckValue` — flags a value frozen within a tolerance band.
- `checkSpike` — modified Z-score / median-absolute-deviation outlier detection,
  suggesting the median as the filtered value.
- `assessDataQuality` — composite check combining the four above.

### 2.9 Industrial Standards Reference (`standards.ts`)

This module embeds a curated reference library of the international standards
and Ghana regulations that govern industrial automation. Code can query
applicable standards for a given domain at runtime, making it easier to surface
the correct compliance context in reports and assessments. Each entry is an
`IndustrialStandard` record with `code`, `title`, `body`, `edition?`, `scope`,
`applicableDomains`, `keyRequirements`, and `ghanaRelevance?`.

- `IEC_STANDARDS` — IEC 61511, IEC 62443, IEC 61131-3, IEC 61158, IEC 61850,
  IEC 60364.
- `ISO_STANDARDS` — ISO 9001, ISO 14001, ISO 45001, ISO 9283, ISO 10816, ISO/IEC
  17025, ISO 13849, ISO 12100.
- `ANSI_ISA_STANDARDS` — ISA-5.1, ISA-18.2, ISA-88, ISA-95, ISA-101.
- `NFPA_STANDARDS` — NFPA 70, NFPA 72.
- `API_STANDARDS` — API RP 14C, API 670.
- `ASME_STANDARDS` — ASME PTC 19.3 TW, ASME B31.3.

`GHANA_REGULATIONS` is a reference library of `GhanaRegulation` records covering
EPA Act 1994 (Act 490), L.I. 1652, Energy Commission Act 1997 (Act 541),
Renewable Energy Act 2011 (Act 832), Minerals and Mining Act 2006 (Act 703),
Ghana Standards Authority Act, Labour Act 2003 (Act 651), Ghana EPA Water
Quality Standards, Factories Offices and Shops Act 1970, and GS 1 electrical
installations.

`getApplicableStandards(domain)` returns all international standards
(`isMandatory: false`) and Ghana regulations (`isMandatory: true`) whose
`applicableDomains` includes the requested domain.

### 2.10 Zod Validation Schemas (`schemas.ts`)

`@brigid/core` ships Zod schemas that validate payloads at the ingestion
boundary. They enforce both field-level constraints (format, range, presence)
and cross-field invariants (e.g., OEE identity, battery capacity bounds). If a
payload fails these schemas, the error is returned to the caller — the record is
never silently stored in a malformed state.

Shared primitive schemas used across multiple object schemas:
`ISODateStringSchema` (`YYYY-MM-DD`), `ISODateTimeStringSchema` (ISO 8601),
`PositiveNumberSchema`, `NonNegativeNumberSchema`, `PercentageSchema` (0–100),
`RatioSchema` (0–1).

The table below lists each object schema and its most important cross-field
validation rules.

| Schema                           | Notable validation                                                                                                       |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `OEEMetricsSchema`               | refines `oee == availability × performance × quality` (±0.001)                                                           |
| `SensorSchema`                   | `tag` must match ISA-5.1 `^[A-Z]{1,4}-\d{3,4}([A-Z])?$`; `protectionClass` must be `IPxx`; refines `rangeMax > rangeMin` |
| `PLCSchema` / `PLCProgramSchema` | `cycleTimeMsec` 0.1–1000; `silRating` `SIL1`/`SIL2`/`SIL3`                                                               |
| `SCADAPointSchema`               | `samplingRateSec` 0.1–86400; refines `engRangeHigh > engRangeLow`                                                        |
| `MaintenanceRecordSchema`        | `title` 3–200 chars; `attachments[].url` must be a URL                                                                   |
| `CalibrationRecordSchema`        | `measurementPoints` must have ≥ 3 entries (ISO 17025); `ambientTemperatureC` −10..50                                     |
| `SolarArraySchema`               | `tiltAngleDeg` 0–90; `azimuthDeg` 0–360; `moduleEfficiencyPct` 5–30; `degradationRateYrPct` 0.1–2                        |
| `BatteryBankSchema`              | refines `usableCapacityKWh ≤ nominalCapacityKWh`                                                                         |
| `RobotSchema`                    | `dof` 1–10; `repeatabilityMm` positive ≤ 5                                                                               |
| `VulnerabilityFindingSchema`     | `cveId` must match `^CVE-\d{4}-\d+$`; `cvssScore` 0–10                                                                   |
| `BOMItemSchema` / `BOMSchema`    | recursive (`z.lazy`); `wasteFactorPct` 0–50                                                                              |
| `ProductionOrderSchema`          | refines `plannedEndDate ≥ plannedStartDate`                                                                              |
| `ElectricityBillInputSchema`     | `energyKWh` and `peakDemandKVA` positive; `voltageLevel` `LV`/`HV`                                                       |

The module also exports the inferred input types (`SensorInput`, `PLCInput`,
`MaintenanceRecordInput`, `CalibrationRecordInput`, `SolarArrayInput`,
`BatteryBankInput`, `RobotInput`, `VulnerabilityFindingInput`, `BOMInput`,
`ProductionOrderInput`, `PLCProgramInput`).

---

## 3. Persistence — `@brigid/db`

`@brigid/db` is the persistence layer for the entire Brigid domain. It provides
a Drizzle ORM schema (not Prisma), a post-migration SQL runner for TimescaleDB
hypertables and pgvector configuration, and seed data for reference equipment,
procedures, and tariffs.

The database is named `brigid` and requires the `timescaledb` and `pgvector`
extensions. The connection string is read from `BRIGID_DATABASE_URL`. `index.ts`
re-exports `schema.ts`, `migrations.ts`, and `seed.ts`.

### 3.1 PostgreSQL Enums (`pgEnum`)

The schema defines native PostgreSQL enum types for all columns that must be
constrained to a fixed value set. Using `pgEnum` rather than plain text columns
lets PostgreSQL enforce valid values at the storage layer, independent of
application-level validation.

| Enum                             | Values                                                                                                                                                     |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `brigid_equipment_status`        | `running`, `idle`, `maintenance`, `fault`, `decommissioned`                                                                                                |
| `brigid_equipment_level`         | `enterprise`, `site`, `area`, `production_line`, `work_cell`, `equipment_unit`, `control_module`                                                           |
| `brigid_maintenance_type`        | `corrective`, `preventive_scheduled`, `preventive_condition_based`, `predictive`, `improvement`, `inspection`, `overhaul`, `statutory`                     |
| `brigid_maintenance_priority`    | `emergency`, `urgent`, `high`, `medium`, `low`, `scheduled`                                                                                                |
| `brigid_work_order_status`       | `draft`, `submitted`, `approved`, `parts_ordered`, `scheduled`, `assigned`, `in_progress`, `pending_parts`, `completed`, `verified`, `closed`, `cancelled` |
| `brigid_energy_source_type`      | `solar_pv`, `battery_storage`, `grid`, `diesel_generator`, `wind`, `biogas`, `hydro`                                                                       |
| `brigid_robot_type`              | `articulated_6dof`, `articulated_7dof`, `SCARA`, `delta_parallel`, `cartesian_gantry`, `collaborative_cobot`, `dual_arm`, `mobile_robot_arm`               |
| `brigid_security_level`          | `SL0`, `SL1`, `SL2`, `SL3`, `SL4`                                                                                                                          |
| `brigid_certificate_status`      | `active`, `expired`, `suspended`, `revoked`, `pending_renewal`                                                                                             |
| `brigid_production_order_status` | `planned`, `released`, `dispatched`, `executing`, `paused`, `completed`, `closed`, `cancelled`                                                             |
| `brigid_alarm_priority`          | `critical`, `high`, `medium`, `low`, `journal`                                                                                                             |

Note: the DB `brigid_work_order_status` enum omits `pending_approval`, which is
present in the `@brigid/core` `WorkOrderStatus` type. The DB enum is the
persistence source of truth for stored work orders; `pending_approval` is a
type-system concept used during the approval flow before a record is committed.

### 3.2 Relational Tables

Every table has a `uuid` `id` primary key (`defaultRandom()`) and most carry
`createdAt` / `updatedAt` `timestamptz` columns. Tables are grouped below by
functional area, following the Phase 59 implementation numbering.

**Facility hierarchy** (59.1.2.1):

- `brigid_sites` — `siteCode` (unique), `name`, `address`, `country` (default
  `Ghana`), `region`, `city`, `lat`, `lon`, `totalFloorAreaM2`, `headcount`,
  `status`, `metadata` (jsonb). Index on `region`.
- `brigid_factories` — FK `siteId → brigid_sites`; `certifications` and
  `utilitySystems` jsonb. Index on `siteId`.
- `brigid_production_areas` — FK `factoryId`; `cleanroomClass`, `hazardousArea`.
  Index on `factoryId`.
- `brigid_production_lines` — `lineId` (unique text), FKs `factoryId`, `areaId`;
  takt/throughput/shift fields, `oeeMetrics` jsonb, `currentJobOrder`. Index on
  `factoryId`.
- `brigid_work_cells` — FKs `lineId`, `factoryId`; station number, cycle and
  setup times, buffer capacities, `isBottleneck`, `automationLevel`.

**Asset registry** (59.1.2.2):

- `brigid_equipment` — `equipmentId` (unique text), `level`
  (`brigid_equipment_level`), `parentId`, `equipmentClass`, FKs `factoryId`,
  `workCellId`; `locationJson`, `oeeMetrics`, `specifications`, `documentRefs`,
  `tags` jsonb; `mtbfHours`, `mttrHours`, `operatingHours`; `status`
  (`brigid_equipment_status`). Indexes on `factoryId`, `status`, `level`.

**Control devices** (59.1.2.3):

- `brigid_sensors` — `sensorId` and `tag` both unique; FK `equipmentId`; range,
  output type, accuracy, `alarmConfiguration` jsonb, `scadaTagAddress`,
  `isOnline`, `lastReadingAt`. Indexes on `equipmentId`, `quantity`.
- `brigid_actuators` — `actuatorId` and `tag` unique; FKs `equipmentId`,
  `feedbackSensorId`; `specifications` jsonb.
- `brigid_plcs` — `plcId` unique; vendor, CPU, firmware, `programs`,
  `ioModules`, `commModules` jsonb; `isRedundant`, `isSafetyRated`, `silRating`.

**Maintenance** (59.1.2.4):

- `brigid_work_orders` — `workOrderId` unique; `maintenanceType`
  (`brigid_maintenance_type`), `priority` (`brigid_maintenance_priority`),
  `status` (`brigid_work_order_status`); FK `equipmentId`; full lifecycle
  timestamps; `laborEntries` and `materialsUsed` jsonb; cost columns are
  `numeric(12,2)`; `functionalTestPassed`, `rootCauseAnalysis`. Indexes on
  `equipmentId`, `status`, `requestedAt`.
- `brigid_spare_parts` — `sparePartId` and `partNumber` unique; stock / reorder
  / lead-time fields; `unitCostGHS` `numeric(12,2)`; `interchangeableParts`,
  `suppliers` jsonb. Indexes on `criticality`, `category`.

**Energy** (59.1.2.5):

- `brigid_energy_systems` — `systemId` unique; FK `siteId`; `sources` and
  `loads` jsonb; `operatingMode`, `controllerType`; Ghana grid-reliability
  columns.
- `brigid_solar_arrays` — `arrayId` unique; FKs `siteId`, `energySystemId`;
  `panelSpecification`, `strings`, `inverters` jsonb; tilt/azimuth, loss
  factors; `averageDailySunHrs` defaults `5.5` (Accra).
- `brigid_battery_banks` — `bankId` unique; FK `energySystemId`; chemistry,
  topology, capacity, DoD (default 90), live SOC/SOH.

**Water** (59.1.2.6):

- `brigid_water_treatment_plants` — `plantId` unique; FK `siteId`;
  `treatmentTrain`, `waterQualityTargets` jsonb; `regulatoryAuthority` default
  `Ghana EPA`; permit fields.
- `brigid_water_quality_readings` — FK `plantId`; `sampledAt`, `samplingPoint`,
  `turbidityNTU`, `pH`, coliform counts, `chlorineResidualMgL`, per-parameter
  and overall compliance booleans. Index on `(plantId, sampledAt)`; converted to
  a TimescaleDB hypertable (see §3.3).

**Robotics** (59.1.2.7):

- `brigid_robots` — `robotId` unique; `type` (`brigid_robot_type`); `kinematics`
  jsonb; `cycleCount` `bigint`; `safeguardingType`, `safetyValidated`,
  `lastSafetyValidationDate`.
- `brigid_robot_cells` — `cellId` unique; FK `factoryId`; `robotIds`,
  `safetyZones`, `applications` jsonb; `riskAssessmentRef`.
- `brigid_robot_programs` — `programId` unique; FK `robotId`; `programUrl`
  (MinIO reference), `checksum`, `isActive`.

**Digital twin** (59.1.2.8):

- `brigid_digital_twins` — `twinId` unique; `physicalAssetId`, `assetType`,
  `fidelity`; `dataBindings`, `kpis` jsonb; sync metadata.
- `brigid_simulation_scenarios` — `scenarioId` unique; FK `twinId`;
  `parameters`, `kpiTargets`, `runs` jsonb; `baselineRunId`, `recommendedRunId`,
  `status`.

**Cybersecurity** (59.1.2.9):

- `brigid_security_assessments` — `assessmentId` unique; FK `siteId`; `zones`,
  `conduits` jsonb; `maturityLevel`, `overallSecurityScore`, per-severity
  finding counts.
- `brigid_vulnerabilities` — `findingId` unique; FK `assessmentId`; `severity`,
  `cveId`, `cvssScore`, `remediationStatus`. Indexes on `assessmentId`,
  `severity`.

**Training** (59.1.2.10):

- `brigid_training_programs` — `programId` unique; `modules` jsonb; `nqfLevel`,
  `costPerTraineeGHS` `numeric(12,2)`.
- `brigid_certifications` — `certificationId` and `certificateNumber` unique; FK
  `programId`; `status` (`brigid_certificate_status`);
  `competencyUnitsAchieved`, `auditHistory`, `cpd` jsonb; `renewalWindowDays`
  default 60. Indexes on `holderId`, `status`, `expiryDate`.

**Materials** (59.1.2.11):

- `brigid_materials_batches` — `batchNumber` unique; `productCategory` (e.g.
  `welding_consumable`, `industrial_gas`, `plastic_compound`);
  `rawMaterialsUsed`, `processParameters`, `qualityTestResults` jsonb;
  `qualityStatus`. Indexes on `productId`, `productionDate`.

**Calibration** (59.1.2.12):

- `brigid_calibration_records` — `calibrationId` and `certificateNumber` unique;
  FK `sensorId`; `referenceStandard` and `measurementPoints` jsonb (both
  `notNull`); `asFoundStatus`, `asLeftStatus`, `result`. Indexes on `sensorId`,
  `calibrationDue`, `result`.

**Aggregates and condition monitoring:**

- `brigid_oee_records` — FK `equipmentId`; `periodStartAt`, `periodEndAt`,
  `granularity` (`shift`/`day`/`week`/`month`); `oee`, `availability`,
  `performance`, `quality`; `downTimeBreakdown` jsonb. Unique index on
  `(equipmentId, periodStartAt, granularity)`; converted to a hypertable.
- `brigid_condition_readings` — FK `equipmentId`; `indicatorId`,
  `parameterType`, `measuredAt`, `value`, `trend`, `alertActive`, `alarmActive`.
  Index on `(equipmentId, measuredAt)`; converted to a hypertable.

### 3.3 Time-Series, Vector and Cache Layers (`migrations.ts`)

Raw sensor telemetry at one-second resolution generates millions of rows per day
per site. Standard PostgreSQL tables cannot absorb that volume efficiently, so
Brigid uses a post-migration step to convert the high-volume tables to
TimescaleDB hypertables and configure automated compression and retention. The
vector extension supports the AI embeddings table. Redis caching keeps the
most-recently-accessed operational state available with sub-second latency.

Post-migration SQL is applied after Drizzle creates the base tables. The
documented full migration order (`FULL_MIGRATION_STEPS`): create database →
grant permissions → `drizzle-kit push` → `TIMESCALEDB_HYPERTABLE_SQL` →
`PGVECTOR_SQL` → `RETENTION_POLICY_SQL` → seed.

**TimescaleDB hypertables** (`TIMESCALEDB_HYPERTABLE_SQL`): enables the
`timescaledb` extension and converts four tables to hypertables —
`brigid_sensor_telemetry` (1-day chunks, partitioned by `timestamp`),
`brigid_water_quality_readings` (1-week chunks), `brigid_oee_records` (1-month
chunks), `brigid_condition_readings` (1-week chunks). `brigid_sensor_telemetry`
is the base telemetry table: `sensorId` FK, `timestamp`, `value` (real),
`quality` (`good`/`bad`/`uncertain`, default `good`), `unit`, `rawValue`
(pre-conversion), `source` (`scada`/`edge`/`manual`, default `scada`); index on
`(sensorId, timestamp)`.

**pgvector** (`PGVECTOR_SQL`): enables the `vector` extension and adds a
`vector(1536)` `embedding` column plus an IVFFlat index (`vector_cosine_ops`,
`lists = 100`) to `brigid_ai_embeddings`. `brigid_ai_embeddings` stores
embedding metadata: `assetId`, `assetType`
(`equipment`/`sensor`/`inspection_image`), `embeddingType`
(`defect_detection`/`predictive_maintenance`/`nlp_description`), `modelName`,
`modelVersion`, `dimensions`.

**Retention and continuous aggregates** (`RETENTION_POLICY_SQL`): defines
continuous aggregates `brigid_telemetry_1min` (1-minute avg/max/min/stddev) and
`brigid_telemetry_1hr` (1-hour rollup of the 1-minute view), with refresh
policies. Retention policies: drop raw `brigid_sensor_telemetry`

> 90 days, compress chunks older than 7 days (`compress_segmentby = sensor_id`,
> `compress_orderby = timestamp DESC`); retain `brigid_water_quality_readings` 2
> years and `brigid_condition_readings` 1 year. The documented tier strategy is
> hot (0–7 days raw 1-second), warm (7–90 days 1-minute aggregate), cold (90
> days–2 years 1-hour aggregate), archive (2 years+ daily aggregates).

**Redis caching strategy** (`REDIS_CACHING_STRATEGY`): a key-builder object with
TTLs. Key convention `brigid:{domain}:{entity}:{id}:{field}`. Keys and TTLs:
live SCADA PV (`brigid:scada:pv:{tag}`, 30 s), active alarms
(`brigid:alarm:active:{tag}`, no TTL — acknowledgement removes), alarm flood
counter (`brigid:alarm:flood:{zone}`, 60 s), active-alarm sorted set, equipment
status (60 s), live OEE (`brigid:oee:{equipmentId}:shift`, 3600 s), energy live
metrics (30 s), battery SOC (30 s), robot status (30 s), SCADA watchdog
heartbeat (10 s), calibration-due sorted set (86400 s), active work orders per
equipment (no TTL).

### 3.4 Seed Data (`seed.ts`)

The seed module provides reference datasets that can be loaded into a fresh
database to give it realistic starting data for development and testing. All
datasets are exported as `const` arrays so they can also be imported directly in
tests without a database connection.

- `REFERENCE_EQUIPMENT_CATALOG` — motors (Siemens, WEG), VFDs (Siemens,
  Allen-Bradley), temperature/pressure sensors and flow meters (Endress+Hauser,
  Emerson, Omron), PLCs (Siemens S7-1500, Allen-Bradley ControlLogix, Mitsubishi
  MELSEC), robots (KUKA KR 10, Universal Robots UR10e), solar panels (JA Solar,
  Canadian Solar), each with manufacturer, model and engineering specs.
- `STANDARD_MAINTENANCE_PROCEDURES` — procedures (`PROC-MOT-001`,
  `PROC-MOT-002`, `PROC-PLC-001`, `PROC-SENSOR-001`, `PROC-SOLAR-001`) with task
  lists, tools, safety precautions, and permit type.
- `GHANA_ENERGY_TARIFFS_SEED` — ECG/PURC LV and HV industrial tariffs, solar
  net-metering export tariff, and Greater Accra grid-reliability data (outages
  per month, SAIDI).
- `SENSOR_TYPE_REFERENCE` — per-quantity common units, typical ranges, and ISA
  instrument-letter codes.

---

## 4. Application Services — `apps/brigid/*`

The five application services each compile to a runnable Node.js process. They
import from the domain libraries but add the HTTP surface, routing, middleware,
and real-time protocols. The central service is `@brigid/api`; the other four
(`factory-os`, `energy-ms`, `maintenance-ms`, `training-lms`) expose
domain-specific operational dashboards and are consumed by the web front-end.

### 4.1 `@brigid/api` — HTTP / SSE / WebSocket API

`apps/brigid/api` is a Hono application (`app.ts`). Global middleware is applied
in this order: `secureHeaders`, `cors`, `logger`, `prettyJSON`. CORS allows
origins `http://localhost:3000`, `:5173`, `:4200`; methods `GET`/`POST`/
`PUT`/`PATCH`/`DELETE`/`OPTIONS`; headers `Content-Type`, `Authorization`,
`X-API-Key`, `X-Site-ID`; rate-limit headers are exposed.

Rate limiting is applied to `/api/*` at 100 requests per 60 seconds. The limiter
(`middleware/rate-limit.ts`) uses an in-memory sliding-window keyed by
`x-forwarded-for` / `x-real-ip` (falling back to `anonymous`). It sets
`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, and on
exceedance returns `429` with `Retry-After` and a `RATE_LIMITED` error.

Authentication is optional per request. If an `Authorization: Bearer` header is
present, `middleware/auth.ts#parseJWT` verifies an HS256 JWT and attaches
`{ userId, email, role, siteId }` to the context. Routes that require
authorization call `requireRole(...)`, which rejects with `401` when
unauthenticated and `403` when the role level is below the minimum.

Health endpoints are available without the `/api` prefix:

| Method | Path      | Purpose                                     |
| ------ | --------- | ------------------------------------------- |
| GET    | `/health` | Liveness — service, version, listed domains |
| GET    | `/ready`  | Readiness — `database`/`cache`/`ml` checks  |

The functional API is mounted at `/api/v1`. All in-route stores are currently
in-memory `Map` structures; the `@brigid/db` schema described in §3 is the
intended persistence target once the route handlers are connected to the
database.

#### 4.1.1 Equipment routes (`/api/v1/equipment`)

The equipment routes manage the asset registry. The `EquipmentRecord` DTO is the
API-facing shape of an asset — note that it uses `status` values (`operational`,
`degraded`, `failed`, `decommissioned`, `standby`) that differ from the
`@brigid/core` `Equipment.status` values; this is an intentional simplification
at the API boundary.

The `EquipmentRecord` DTO: `id`, `name`, `tag`, `siteId`, `areaId?`,
`assetType`, `manufacturer?`, `model?`, `serialNumber?`, `criticality`
(`1|2|3|4`), `status` (`operational`/`degraded`/`failed`/`decommissioned`/
`standby`), `healthScore`, `replacementValue`, `parentId?`, `installDate?`,
`createdAt`, `updatedAt`, `deletedAt?`.

| Method | Path                       | Auth (min role)    | Purpose                                                        |
| ------ | -------------------------- | ------------------ | -------------------------------------------------------------- |
| GET    | `/equipment`               | none               | List; query `page`, `limit` (≤100), `siteId`, `areaId`, `type` |
| GET    | `/equipment/:id`           | none               | Single equipment                                               |
| POST   | `/equipment`               | `factory_engineer` | Create (requires `name`, `siteId`, `assetType`) → `201`        |
| PUT    | `/equipment/:id`           | `factory_engineer` | Update                                                         |
| DELETE | `/equipment/:id`           | `factory_manager`  | Soft delete (sets `deletedAt`)                                 |
| GET    | `/equipment/:id/hierarchy` | none               | Recursive parent→children asset tree                           |
| POST   | `/equipment/bulk`          | `factory_engineer` | Bulk create/update → `207`                                     |

#### 4.1.2 Telemetry routes (`/api/v1/telemetry`)

The telemetry routes handle high-volume sensor data ingestion and retrieval.
Batching (up to 1000 readings per request) reduces round-trip overhead for edge
devices. Out-of-order readings are inserted in time order rather than rejected,
which tolerates network jitter and buffered delivery.

The `TelemetryReading` DTO: `assetId`, `tag`, `value`, `unit`, `quality`
(`good`/`uncertain`/`bad`), `timestamp`. A `TelemetryBatch` is
`{ readings, sourceId? }`.

| Method | Path                          | Purpose                                                                                                                  |
| ------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| POST   | `/telemetry`                  | Ingest a batch (≤1000 readings); returns `{ accepted, rejected, errors, ingestedAt }`; `202` if any accepted, else `400` |
| GET    | `/telemetry/:assetId`         | Latest reading per tag for an asset                                                                                      |
| GET    | `/telemetry/:assetId/history` | Time-series query; query `tag`, `from`, `to`, `limit` (≤5000)                                                            |

Readings are stored sorted by timestamp; out-of-order readings are inserted in
time order. The store caps each tag at 10000 readings.

#### 4.1.3 Maintenance routes (`/api/v1/maintenance`)

The maintenance routes expose the work-order lifecycle, PM schedule management,
spare-parts inventory, and KPI computation. New work orders are created with
`status` `OPEN` and a generated `woNumber` (`WO-{year}-{0000}`).

DTOs: `WorkOrderDTO` (`id`, `woNumber`, `title`, `type`, `priority`, `status`,
`assetId`, `siteId`, `description`, `estimatedHours`, `assignedTo?`,
`createdAt`), `PMScheduleDTO`, `SparePartDTO`.

| Method | Path                           | Purpose                                                                            |
| ------ | ------------------------------ | ---------------------------------------------------------------------------------- |
| GET    | `/maintenance/work-orders`     | List; query `status`, `assetId`                                                    |
| GET    | `/maintenance/work-orders/:id` | Single work order                                                                  |
| POST   | `/maintenance/work-orders`     | Create (requires `title`, `assetId`, `siteId`) → `201`                             |
| PUT    | `/maintenance/work-orders/:id` | Update                                                                             |
| GET    | `/maintenance/pm-schedules`    | List PM schedules; query `assetId`                                                 |
| POST   | `/maintenance/pm-schedules`    | Create (computes `nextDueAt` from `intervalDays`) → `201`                          |
| GET    | `/maintenance/spare-parts`     | List spare parts                                                                   |
| POST   | `/maintenance/spare-parts`     | Create spare part → `201`                                                          |
| GET    | `/maintenance/kpis`            | MTBF / MTTR / availability computed from work-order data; query `siteId`, `period` |

#### 4.1.4 Energy routes (`/api/v1/energy`)

The energy routes expose real-time generation and storage state plus the
energy-audit submission endpoint. The in-memory store is seeded with `site-1`
solar, battery, and grid status for development use.

DTOs: `SolarStatus`, `BatteryStatus`, `GridStatus`, `AuditReading`.

| Method | Path              | Purpose                                                                      |
| ------ | ----------------- | ---------------------------------------------------------------------------- |
| GET    | `/energy/solar`   | Solar generation status; query `siteId` (default `site-1`)                   |
| GET    | `/energy/battery` | Battery SOC / SOH status                                                     |
| GET    | `/energy/grid`    | Grid import/export, power factor, frequency, tariff                          |
| GET    | `/energy/summary` | Combined solar/battery/grid summary with self-sufficiency rate               |
| POST   | `/energy/audit`   | Submit audit readings (requires `siteId`, `submittedBy`, `readings`) → `201` |

#### 4.1.5 AI routes (`/api/v1/ai`)

The AI routes are the HTTP surface for the `@brigid/ai-industrial` library.
Confidence scores are computed by deterministic helper functions
(`calculatePredictionConfidence`, `calculateVisionConfidence`,
`calculateOptimizationConfidence`) from request properties — not randomly
generated.

DTOs include `VisionInspectionRequest`/`VisionInspectionResult`,
`PredictionResult`, `OptimizationRequest`/`OptimizationRecommendation`.
`VisionInspectionRequest.inspectionType`: `surface_defect`, `corrosion`, `wear`,
`alignment`, `leak`.

| Method | Path                       | Purpose                                                                                                |
| ------ | -------------------------- | ------------------------------------------------------------------------------------------------------ |
| POST   | `/ai/vision/inspect`       | Image-based inspection (requires `assetId`, `inspectionType`, and `imageBase64` or `imageUrl`) → `202` |
| GET    | `/ai/predictions/:assetId` | Per-asset RUL / failure-probability predictions; default prediction for unknown assets                 |
| POST   | `/ai/optimize`             | Process-parameter optimization recommendations (requires `processId`, `currentParameters`)             |

Confidence scores are computed by deterministic helper functions
(`calculatePredictionConfidence`, `calculateVisionConfidence`,
`calculateOptimizationConfidence`) from request properties — not random.

#### 4.1.6 Training routes (`/api/v1/training`)

The training routes support the full learner journey from enrollment through
certification. The in-memory course store is seeded with three courses
(`PLC-101`, `OHS-101`, `SCADA-201`) for development use.

DTOs: `CourseDTO`, `EnrollmentDTO`, `AssessmentSubmission`, `CertificationDTO`.

| Method | Path                                  | Purpose                                                                                                    |
| ------ | ------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| GET    | `/training/courses`                   | List published courses; query `category`, `level`                                                          |
| POST   | `/training/enroll`                    | Enroll a learner (requires `courseId`, `learnerId`); `404` if no course, `409` if already enrolled → `201` |
| GET    | `/training/progress/:learnerId`       | Learner enrollment count, progress, completed courses                                                      |
| POST   | `/training/assessment/submit`         | Submit an assessment answer                                                                                |
| GET    | `/training/certifications/:learnerId` | Certifications held by a learner                                                                           |

#### 4.1.7 Cross-domain routes (`/api/v1/cross-domain`)

The cross-domain routes are the HTTP surface for the `@brigid/cross-domain`
adapter. They accept inbound requests from partner domains and emit
`CrossDomainEvent` objects onto an internal queue, which is replayed to
subscribers over SSE. Both POST endpoints append an event to this queue.

DTOs: `EquipmentProvisionRequest`, `MaintenanceRequestDTO`, `CrossDomainEvent`.

| Method | Path                                | Purpose                                                                                                                                                  |
| ------ | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| POST   | `/cross-domain/equipment-provision` | Submit an equipment provisioning request (requires `equipmentType`, `siteId`, `requestedBy`); emits `EQUIPMENT_PROVISION_REQUESTED` → `202`              |
| POST   | `/cross-domain/maintenance-request` | Submit a cross-domain maintenance request (requires `equipmentId`, `issueDescription`, `sourceSystem`); emits `CROSS_DOMAIN_MAINTENANCE_REQUEST` → `202` |
| GET    | `/cross-domain/telemetry/subscribe` | Server-Sent Events stream replaying the last 10 queued events plus a heartbeat                                                                           |

#### 4.1.8 WebSocket routes (`/ws/factory`)

The factory WebSocket provides a real-time push channel for plant-floor events —
SCADA updates, alarms, OEE data, and asset state changes — to connected
dashboard clients. It is mounted at the root (not under `/api/v1`). A
`GET /ws/factory` without a WebSocket `Upgrade` header returns connection
metadata; with the header it returns `426` (the actual upgrade is handled by the
Node.js `@hono/node-ws` adapter).

`FactoryWSMessageType` literal union: `SCADA_UPDATE`, `ALARM_ACTIVE`,
`ALARM_CLEARED`, `OEE_UPDATE`, `ASSET_STATUS_CHANGE`, `WORK_ORDER_UPDATE`,
`SUBSCRIBE`, `UNSUBSCRIBE`, `PING`, `PONG`. Message payload DTOs:
`SCADATagUpdate`, `AlarmEvent` (`alarmId`, `assetId`, `tag`, `message`,
`priority`, `activatedAt`, `acknowledgedAt?`, `clearedAt?`), `OEEData`.
`createWebSocketHandler()` provides `onOpen`/`onMessage`/`onClose`/`onError`
handlers — on open it sends a welcome message; it answers `PING` with `PONG` and
`SUBSCRIBE` with a subscription acknowledgement.

#### 4.1.9 Authentication and RBAC (`middleware/auth.ts`)

The auth middleware implements a five-level role hierarchy. Each level
numerically encompasses all levels below it, so a `factory_manager` can do
everything a `factory_engineer` can. Routes declare a minimum role; the
middleware enforces it.

`FactoryRole` literal union and `ROLE_HIERARCHY` numeric levels:
`factory_viewer` (1), `factory_operator` (2), `factory_engineer` (3),
`factory_manager` (4), `super_admin` (5). `JWTPayload` carries `sub`, `email`,
`role`, optional `siteId`, `iat`, `exp`.

JWTs are HS256, signed/verified with a secret resolved from `BRIGID_JWT_SECRET`
→ `JWT_SECRET`, falling back to a fixed development secret outside production;
in production a missing secret throws. Signature comparison uses
`timingSafeEqual`. `parseJWT` rejects malformed structure, non-HS256 headers,
bad signatures, invalid payloads and expired tokens. `createJWT` mints tokens
(default 1-hour expiry). `requireRole(minRole)` enforces
`ROLE_HIERARCHY[userRole] ≥ ROLE_HIERARCHY[minRole]`.

### 4.2 `@brigid/factory-os` — Factory Operations Dashboard

`apps/brigid/factory-os` is the real-time operating environment for plant
engineers and operators. It exports nine modules (Phase 59.22.1):
`production-monitor`, `scada-overview`, `scheduler`, `quality-management`,
`alarm-management`, `shift-handover`, `kpi-dashboard`, `digital-twin`,
`batch-management`. Together these surface: live OEE and output, SCADA equipment
status and process variables, Gantt-based production scheduling with conflict
detection, SPC quality dashboards, ISA-18.2 alarm management with
acknowledgement and shelving, digital shift handover, factory KPIs, the 3D
digital-twin viewer, and recipe/batch execution.

### 4.3 `@brigid/energy-ms` — Energy Management System

`apps/brigid/energy` is the operational energy management application. It
exports eight modules (Phase 59.22.2): `architecture`, `solar-monitor`,
`battery-management`, `power-distribution`, `energy-cost`, `microgrid-control`,
`energy-audit`, `carbon-tracker`. These cover: solar PV monitoring, battery
SOC/charge management, single-line power distribution and power quality, tariff
and demand-charge cost tracking, microgrid source switching and islanding, ISO
50001 energy audit reporting, and carbon-footprint tracking.

### 4.4 `@brigid/maintenance-ms` — Maintenance Management

`apps/brigid/maintenance` is the maintenance operations application. It exports
eight modules (Phase 59.22.3): `architecture`, `work-order`, `asset-management`,
`predictive-maintenance`, `spare-parts`, `maintenance-kpi`, `remote-monitoring`,
`mobile-api`. These cover: work-order creation/assignment/completion workflow,
asset hierarchy and health, RUL and anomaly-driven predictive maintenance,
spare-parts inventory with reorder alerts, MTBF/MTTR/availability KPIs,
multi-site remote monitoring, and an offline-capable mobile technician API.

### 4.5 `@brigid/training-lms` — Training Academy Platform

`apps/brigid/training` is the industrial training LMS. It exports eight modules
(Phase 59.22.4): `architecture`, `course-catalog`, `virtual-lab`, `assessment`,
`certification`, `learner-progress`, `instructor-management`,
`corporate-training`. These cover: course catalog with prerequisites and
enrollment, browser-based PLC/SCADA/HMI virtual lab, practical and theoretical
assessment delivery, certification expiry and renewal tracking, learner progress
with a skills radar, instructor scheduling and qualifications, and corporate
bulk-enrollment and billing.

---

## 5. Domain Library Capabilities (`libs/brigid/*`)

Each library implements named industrial-engineering algorithms, not generic
CRUD. Where the sections below cite an algorithm family (e.g. "Ranked Positional
Weights", "Rasch IRT", "LOPA"), that algorithm is present in the source — not
just referenced in comments. The module names cited are the actual filenames
under each `src/` directory. The algorithm families are documented in each
module's source header.

### 5.1 `@brigid/factory` (Phase 59.3)

This is the largest and most algorithmically dense library in the domain. Its
seven modules span the entire factory-automation stack from line design through
safety-system design.

Modules: `production`, `plc`, `scada`, `communications`, `motion`, `safety`,
`batch`. `production.ts` implements takt-time calculation, Ranked Positional
Weights line balancing (Helgeson & Birnie), M/M/1 and M/G/1 buffer sizing, OEE
with six big losses, dispatching rules (SPT/EDD/FIFO/CR) and a genetic-algorithm
scheduler, Theory-of-Constraints bottleneck identification, discrete-event
simulation, and Systematic Layout Planning. `scada.ts` defines the ISA-18.2
`AlarmState` machine — `NORM`, `UNACK`, `ACKED`, `RTNUN`, `SHELVED`,
`SUPPRESSED`, `INHIBITED` — with `AlarmPriority` `1`–`4`. `batch.ts` implements
the ISA-88 recipe model (`RecipeLevel` `general`/`site`/`master`/`control`;
`ProcedureLevel` `procedure`/`unit_procedure`/`operation`/`phase`) with
`ISA88Recipe`, `RecipeVersion`, `PLCDownloadPackage`, and continuous-process
design. `safety.ts` implements LOPA (`LOPAHazard`, `LayerOfProtection`,
`LOPAResult`, `RiskCategory` `tolerable`/`ALARP`/`intolerable`), SIF design with
`SystemArchitecture` (`1oo1`/`1oo2`/`2oo2`/`1oo2D`/`2oo3`/`1oo3`), proof-test
procedures, ESD cause-and-effect matrices, ISO 12100/13849 machine risk
assessment, and safety-circuit design.

### 5.2 `@brigid/machines` (Phase 59.4)

Modules: `design-workflow`, `mechanical`, `electrical`, `bom-assembly`,
`compliance`. `design-workflow.ts` defines the phase-gate process:
`MachineDesignPhase` literal union `concept`, `detail_design`, `procurement`,
`assembly`, `testing`, `commissioning`, with `GateDecision`
`pass`/`conditional_pass`/`hold`/`kill` and `WorkflowPhaseStatus.status`
`not_started`/`in_progress`/`gate_review`/`completed`/`on_hold`. It generates
Functional Design Specifications and a CPM Gantt schedule, and runs Engineering
Change Order impact analysis (`ECOStatus`). `bom-assembly.ts` defines
`BOMStatus` `design`/`released`/`obsolete`/ `on_order`/`received`.

### 5.3 `@brigid/ai-industrial` (Phase 59.5)

Modules: `computer-vision`, `predictive-maint`, `process-optim`, `robotics-ai`,
`edge-ai`, `sota`, `api-types`. Covers image-based defect detection, anomaly
detection and remaining-useful-life prediction, process setpoint optimization,
robotics AI, and edge deployment, plus the application-facing API types in
`api-types.ts`.

### 5.4 `@brigid/energy` (Phase 59.6)

Modules: `solar`, `bess`, `grid-hybrid`, `power-quality`, `ghana-energy`.
Implements solar PV system design, battery energy storage sizing, grid and
hybrid configuration, power-quality analysis, and Ghana-specific energy
modelling.

### 5.5 `@brigid/maintenance` (Phase 59.7)

Modules: `condition-monitoring` (Weibull reliability, health scoring, alert
engine), `cmms` (work-order management, PM scheduling, asset hierarchy),
`spare-parts` (Economic Order Quantity, safety stock, criticality analysis,
auto-reorder), `kpi-analytics` (MTBF/MTTR, downtime Pareto, backlog, maturity
assessment), `remote-iot` (IoT ingestion, SLA management, warranty tracking,
AR-guided maintenance).

### 5.6 `@brigid/robotics` (Phase 59.8)

Modules: `cobot` (collaborative robot deployment), `robot-programming`
(programming and simulation), `agv-warehouse` (AGV/AMR fleet and warehouse
automation), `robot-safety` (robot safety and human-robot interaction).

### 5.7 `@brigid/digital-twin` (Phase 59.9)

Modules: `factory-twin`, `equipment-twin`, `process-simulation`,
`virtual-commissioning`. `factory-twin.ts` defines `EquipmentOperationalStatus`
`IDLE`/`RUNNING`/`FAULT`/`MAINTENANCE`/ `OFFLINE`; `equipment-twin.ts` defines
`EquipmentState` `IDLE`/`RUNNING`/ `FAULT`/`MAINTENANCE` and
`HealthIndicatorStatus` `normal`/`watch`/ `warning`/`critical`/`unknown`.

### 5.8 `@brigid/cybersecurity` (Phase 59.10)

Four modules. `assessment.ts` — OT security assessment framework
(`OTSecurityAssessmentFramework`, IEC 62443 foundational requirements and
`SecurityLevel`), zone-and-conduit modeling (Purdue levels), gap analysis,
vulnerability scanning, ALARP risk assessment (`ALARP_RISK_MATRIX`), and asset
inventory scanning. `network-security.ts` — network segmentation designer
(Purdue zones), firewall ACL generation, industrial DMZ and data diode design,
remote-access design, network monitoring. `threat-detection.ts` — an industrial
IDS engine with per-protocol packet models (`ModbusPacket`, `DNP3Packet`,
`S7CommPacket`, `OPCUAPacket`), CUSUM-based anomaly detection,
threat-intelligence integration mapping ICS ATT&CK techniques and CVEs,
incident-response orchestration, a forensics toolkit, and a SIEM-for-OT
correlation engine. `access-control.ts` — OT RBAC, patch management with testing
stages, change management, backup verification, security-awareness training, and
a penetration-test methodology.

### 5.9 Vertical Industry Libraries (Phases 59.11–59.16, 59.18)

Each vertical library adds the domain-specific model on top of the §2 core
types. An engineer working in mining, for example, finds `fleet-logistics` and
`process-automation` modules that use the same `Equipment`, `Sensor`, and
`MaintenanceRecord` types from `@brigid/core` — the verticals extend, not
replace, the foundation.

- `@brigid/mining` (59.11) — `fleet-logistics`, `process-automation`,
  `safety-environment`: haul-truck fleet, conveyor and processing-plant
  automation, mine safety and environmental compliance.
- `@brigid/oil-gas` (59.12) — `upstream`, `midstream`, `downstream`,
  `safety-compliance`: well, pipeline and refinery process control across the
  value chain.
- `@brigid/packaging` (59.13) — `primary-packaging`, `secondary-packaging`,
  `line-optimization`, `inspection`, `packaging-materials`: filling / sealing /
  labeling / palletizing line modelling and inspection.
- `@brigid/agricultural-mech` (59.14) — `irrigation`, `greenhouse`,
  `post-harvest`, `livestock-aquaculture`: irrigation automation, greenhouse
  control, post-harvest equipment, livestock and aquaculture systems.
- `@brigid/water` (59.15) — `water-treatment`, `wastewater`,
  `industrial-effluent`: treatment process control and discharge-compliance
  monitoring.
- `@brigid/hvac` (59.16) — `hvac-design`, `refrigeration`,
  `pharma-cold-storage`, `energy-compliance`: HVAC design, refrigeration,
  pharmaceutical cold storage, and energy compliance.
- `@brigid/materials` (59.18) — `plastics-recycling`, `welding-consumables`,
  `industrial-gases`: production, quality and inventory for industrial
  materials.

### 5.10 `@brigid/training` (Phase 59.17)

The training library implements psychometric and pedagogical algorithms — not
just data models — to support competency-based qualification under the Ghana NVQ
framework. Three modules cover curriculum design, assessment, and delivery.

`curriculum.ts` — Bloom's taxonomy (`BloomLevel`, `BLOOM_VERBS`,
`detectBloomLevel`), learning-objective scoring, credit-hour calculation,
prerequisite-graph validation, and pre-built PLC, robotics, electrical,
mechanical, instrumentation, energy, water-treatment and cybersecurity
curricula. `assessment.ts` — Rasch Item Response Theory (`raschProbability`,
`estimateAbility`), Cronbach's alpha reliability, the Ghana NVQ competency
framework (`GHANA_NVQ_UNITS`), certification status tracking, skills-gap
analysis, and continuing professional development. `delivery.ts` —
Kirkpatrick-model training ROI, topological learning-path generation,
spaced-repetition micro-learning (forgetting-curve retention), apprenticeship
management, hands-on training scheduling, instructor management, and a virtual
lab environment.

### 5.11 `@brigid/market-intel` and `@brigid/financials` (Phases 59.19–59.20)

- `@brigid/market-intel` — `market-analysis`, `sector-demand`, `business-dev`:
  industrial market analysis, sector demand modelling, and business-development
  opportunity scoring.
- `@brigid/financials` — `bu-models`, `pricing-costing`, `portfolio-analysis`:
  financial models for the Brigid business units, pricing and costing, and
  portfolio-level analysis.

### 5.12 `@brigid/supply-chain` and `@brigid/weighing` (Phases 59.25, 59.24)

- `@brigid/supply-chain` — `logistics`, `planning`: logistics planning and
  demand/inventory planning.
- `@brigid/weighing` — `weighing-systems` and `calibration`. Weighing-system
  design covers weighbridges, batch weighing, checkweighers, tank weighing and
  belt weighers with `OIMLClass` accuracy classes (OIML R 76 / R 50 / R 51).
  `calibration.ts` implements a calibration management system, GUM-based
  measurement-uncertainty calculation (`UncertaintyDistribution`, uncertainty
  budgets), a calibration-procedure library, certificate generation, and
  instrument-drift analysis, aligned to ISO/IEC 17025:2017 and the GUM (ISO/IEC
  Guide 98-3).

### 5.13 `@brigid/sota-enhancements` (Phase 59.23)

Modules: `human-centric`, `edge-ai`, `5g-remote-ops`, `ar-vr`, `generative-ai`,
`reinforcement-learning`, `federated-learning`, `digital-thread-quantum`. These
carry the Phase 59.23 state-of-the-art enhancements to industrial automation, AI
and robotics, depending on the same foundation contracts.

---

## 6. Cross-Domain Integration — `@brigid/cross-domain`

`@brigid/cross-domain` is the only sanctioned exit point from the Brigid domain.
External domains import from this package only — never from `@brigid/core`,
`@brigid/factory`, or any other internal library. The package exports five
integration adapter groups and a set of Zod API contracts that define the shapes
of cross-domain requests and responses.

### 6.1 Integration Adapters

Each adapter group exposes Brigid capabilities to one consumer domain via named
integration classes. The adapter maps Brigid's internal DTOs into
consumer-facing design objects (e.g. `ProcessingLineDesign`, `ColdRoomDesign`,
`BatteryAssemblyLineDesign`, `SMTLineDesign`, `CarbonFootprint`,
`EnergyBenchmark`), so consumers work with concepts from their own domain
vocabulary rather than Brigid's.

| Consumer                               | Integration classes                                                                                                                                                                              |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Asase (agriculture & food)             | `FoodProcessingAutomationIntegration`, `ColdChainIntegration`, `AgriculturalMechanizationIntegration`, `PostHarvestEquipmentIntegration`, `FoodSafetyAutomationIntegration`                      |
| Freya (beauty, fashion & textiles)     | `TextileManufacturingIntegration`, `CosmeticsProductionIntegration`, `GarmentManufacturingIntegration`, `PackagingLineIntegration`                                                               |
| Cybele (construction & infrastructure) | `PrefabHousingFactoryIntegration`, `BuildingMaterialsIntegration`, `DataCenterPowerIntegration`, `ConstructionEquipmentIntegration`                                                              |
| Saraswati (technology & electronics)   | `EVBatteryManufacturingIntegration`, `SolarPanelManufacturingIntegration`, `ElectronicsAssemblyIntegration`, `PCBManufacturingIntegration`                                                       |
| Maat (data & analytics)                | `FactoryTelemetryDashboardIntegration`, `EquipmentUtilizationAnalyticsIntegration`, `PredictiveMaintenanceAnalyticsIntegration`, `SupplyChainAnalyticsIntegration`, `EnergyAnalyticsIntegration` |

Note: the Freya integration exists in code and is part of this contract surface,
even though it is not listed in some earlier documentation.

### 6.2 Cross-Domain API Contracts (Zod)

`cross-domain/src/api-contracts.ts` exports the Zod schemas that govern requests
and responses at each integration boundary. These are the schemas that consumer
domains validate against when they call Brigid's API or receive events from it.

The file exports the following request/response schema pairs:

- `BrigidEquipmentProvisioningRequestSchema` / `...ResponseSchema` — request
  `requestingDomain` enum `asase`/`freya`/`cybele`/`saraswati`/ `maat`; response
  `status` `quoted`/`confirmed`/`in_production`/ `delivered`/`cancelled` with
  `quoteGHS` and `leadTimeDays`.
- `BrigidEnergyIntegrationRequestSchema` — `siteId`, `requestingDomain`,
  `energyDemandKW`, `peakDemandKW`, `tariffRateGHSPerKWh`, `prefersSolar`,
  `batteryBackupHours`.
- `BrigidMaintenanceServiceRequestSchema` / `...ResponseSchema` — request
  `severity` `critical`/`high`/`medium`/`low`; response `ticketId`,
  `estimatedResolutionHours`, `sparePartsRequired`.
- `BrigidTelemetryEventSchema` — `deviceId`, `siteId`, `timestamp`, `readings`
  (each `{ tagName, value, unit, quality }` with `quality`
  `good`/`bad`/`uncertain`), `alarms`.
- `BrigidTrainingEnrolmentRequestSchema` — `employeeId`, `employerDomain` enum
  (incl. `internal`), `courseId`, `sponsorshipGHS`, `apprenticeshipTrack`.
- `BrigidCertificationRecordSchema` — `grade` `distinction`/`merit`/`pass`/
  `fail`; `issuedBy` is the literal `Brigid Training Academy`.

---

## 7. Events

Brigid currently exposes events through two real-time channels: a WebSocket for
plant-floor clients and a Server-Sent Events stream for cross-domain consumers.
There is no published platform-event catalog (no `AssetRegistered`,
`TelemetryIngested`, etc. event constants exist in the Brigid source). The
implemented event surface is:

### 7.1 WebSocket message types (`@brigid/api`)

`FactoryWSMessageType`: `SCADA_UPDATE`, `ALARM_ACTIVE`, `ALARM_CLEARED`,
`OEE_UPDATE`, `ASSET_STATUS_CHANGE`, `WORK_ORDER_UPDATE`, plus the control
messages `SUBSCRIBE`, `UNSUBSCRIBE`, `PING`, `PONG`. Payloads carry
`SCADATagUpdate`, `AlarmEvent` or `OEEData`.

### 7.2 Cross-domain SSE events (`@brigid/api`)

`CrossDomainEvent` objects (`eventId`, `eventType`, `sourceSystem`, `payload`,
`timestamp`) are appended to an internal queue and replayed over
`GET /api/v1/cross-domain/telemetry/subscribe`. Emitted `eventType` values:
`EQUIPMENT_PROVISION_REQUESTED` (from `brigid-factory`) and
`CROSS_DOMAIN_MAINTENANCE_REQUEST` (from the requesting source system).

### 7.3 Alarm state (`@brigid/factory`)

SCADA alarm transitions are modelled by the ISA-18.2 `AlarmState` machine
(`NORM`/`UNACK`/`ACKED`/`RTNUN`/`SHELVED`/`SUPPRESSED`/`INHIBITED`) in
`factory/src/scada.ts`.

A formal cross-factory event bus (Kafka topics for alarms, production and
quality data, MQTT for IoT) is described in `features.md` and Phase 59.1.3 but
is not expressed as Brigid event-constant code; treat it as infrastructure-level
/ `(planned)` until such code lands.

---

## 8. Configuration and Environment Inputs

The table below lists every environment variable that Brigid reads at startup.
Variables not listed here (bound CORS origins, rate limits, batch limits, Redis
TTLs) are configured in code in the locations cited in §4.1 and §3.3.

| Variable                           | Used by       | Purpose                                                                     |
| ---------------------------------- | ------------- | --------------------------------------------------------------------------- |
| `BRIGID_DATABASE_URL`              | `@brigid/db`  | PostgreSQL (with TimescaleDB + pgvector) connection string                  |
| `BRIGID_JWT_SECRET` / `JWT_SECRET` | `@brigid/api` | HS256 JWT signing/verification secret; required in production               |
| `NODE_ENV`                         | `@brigid/api` | `production` hides internal error detail and forces a configured JWT secret |

The Hono API's bound origins (`localhost:3000`/`:5173`/`:4200`), the 100 req /
60 s rate limit, the telemetry batch limit (1000) and per-tag cap (10000), and
the Redis key TTLs are configured in code (see §4.1, §3.3).

---

## 9. Invariants and Hard Requirements

The constraints below are expressed in the implemented code — they are enforced
by Zod schemas, Drizzle table definitions, and API middleware, not just stated
as policies. If any of them is violated, the system rejects the operation rather
than storing an inconsistent record.

- **OEE identity.** `OEEMetricsSchema` rejects any `OEEMetrics` whose `oee`
  differs from `availability × performance × quality` by more than 0.001.
- **Battery capacity.** `BatteryBankSchema` rejects a bank whose
  `usableCapacityKWh` exceeds its `nominalCapacityKWh`.
- **Production order dates.** `ProductionOrderSchema` rejects a `plannedEndDate`
  earlier than `plannedStartDate`.
- **Sensor range.** `SensorSchema` rejects `rangeMax ≤ rangeMin`; the `tag` must
  match the ISA-5.1 pattern; `protectionClass` must be a valid `IPxx` rating.
- **SCADA point range.** `SCADAPointSchema` rejects
  `engRangeHigh ≤ engRangeLow`.
- **Calibration point count.** `CalibrationRecordSchema` requires at least three
  `measurementPoints` (ISO 17025).
- **CVE identifier format.** `VulnerabilityFindingSchema` rejects a `cveId` that
  does not match `^CVE-\d{4}-\d+$`.
- **Telemetry ingestion tolerance.** The `/api/v1/telemetry` POST endpoint
  accepts batches of at most 1000 readings, inserts out-of-order readings in
  time order, and returns a per-batch `{ accepted, rejected }` count rather than
  failing the whole batch.
- **Data-quality propagation.** `quality` (`good`/`uncertain`/`bad` in the API
  and telemetry table; `good`/`suspect`/`bad` in the `validators.ts`
  data-quality checks) travels with every reading; the data-quality validators
  flag out-of-range, fast-changing, stuck and spike values rather than silently
  dropping them.
- **RBAC enforcement.** Equipment create/update/bulk require at least
  `factory_engineer`; equipment delete requires `factory_manager`; `requireRole`
  rejects with `401` when unauthenticated and `403` below the required level.
- **JWT integrity.** `parseJWT` verifies the HS256 signature with
  `timingSafeEqual`, rejects non-HS256 headers and expired tokens, and in
  production refuses to start without a configured signing secret.
- **Unique business keys.** Each `@brigid/db` registry table enforces a unique
  business identifier (`siteCode`, `equipmentId`, `sensorId`, `tag`,
  `workOrderId`, `partNumber`, `certificateNumber`, `calibrationId`, etc.)
  alongside the surrogate UUID primary key.
- **Time-series retention.** Raw `brigid_sensor_telemetry` is dropped after 90
  days and compressed after 7 days; aggregates are retained per the tiered
  policy in §3.3.

### 9.1 Safety and Audit Requirements

These requirements from `features.md` §19 have type-level support built into the
implemented code:

- **Deterministic fallback** — workflows touching safety-critical assets must
  enter a defined safe state on validation failure, sensor loss, or model
  uncertainty. `@brigid/core` `SafetySystem.failSafeAction` and
  `bypassProcedure` record what that state is and how to enter it;
  `inhibitCount` tracks active bypasses.
- **OT audit trail** — every OT cybersecurity policy decision and operator
  control override must be written to an audit log. The `@brigid/cybersecurity`
  access-control and change-management modules provide the recording mechanism.
- **Immutable calibration records** — maintenance and calibration records must
  be immutable after signoff, with corrections expressed as append-only
  correction events. The ISO/IEC 17025 `CalibrationRecord` type enforces this at
  the data model level.

---

## 10. Verification Expectations

Each library and app ships a Vitest suite (`*.test.ts` alongside the source).
Per `features.md` §19 and `architecture.md`, changes to Brigid run the affected
packages' tests, type checks, linting, and contract checks, plus integration
tests for affected app services.

Industrial-safety, cybersecurity, and control-path changes additionally require
focused tests that cover:

- **Validation behavior** — the schema must reject every malformed payload
  described in §2.10 and §9.
- **Fallback behavior** — safety-critical workflows must enter the documented
  fail-safe state on the error conditions described in §9.1.
- **Audit events** — every OT decision and operator override must produce an
  audit record with the correct actor, timestamp, and rationale.
- **Permission boundaries** — role-restricted routes must reject requests below
  the minimum role level with the correct HTTP status codes.
