Industrial Automation Intelligence bounded context (
libs/brigid/*,apps/brigid/*; TODO Phase 59). Architectural overview: layered package structure, the shared@brigid/coretype system, the engineering and condition-monitoring algorithms in the capability libraries, the Hono API surface, persistence design, and the cross-domain boundary — with honest implemented-vs-planned status.
Brigid is the industrial-automation bounded context for the Oshun platform. It provides the type system, engineering calculations, condition-monitoring and AI algorithms, persistence schema, and application surfaces for factory automation, industrial energy, maintenance, robotics, process industries, OT cybersecurity, and the technical workforce — the full stack from plant-floor sensor to operational dashboard.
The domain exists because industrial operations generate a category of data and decision-making fundamentally different from commerce, content, or finance: physical safety constraints, deterministic control paths, OT-grade cybersecurity requirements, multi-site equipment hierarchies, and calibration records that must survive regulatory audit. Brigid keeps all of that logic in one place so that partner domains (Asase, Freya, Cybele, Saraswati, Maat) can consume plant intelligence without re-implementing it.
Brigid is an implemented TypeScript workspace — 238 source files across 24
library packages (libs/brigid/*) and five application services
(apps/brigid/*), all @brigid/*-scoped. There are zero Rust or Python files
in the domain today: the polyglot stack the package README aspires to (Rust
edge control, Python ML, Kafka/MQTT/OPC-UA transport, WASM HMI) is roadmap, not
code. Everything described below as "implemented" is real, runnable TypeScript;
everything else is explicitly labelled (planned).
Workspace Shape#
Libraries live under libs/brigid/ in four bands — foundation, capability
domains, vertical-industry libraries, and support modules. Application services
live under apps/brigid/ and expose those libraries as operational workflows.
apps/brigid/
api/ ← Hono HTTP / SSE / WebSocket surface (@brigid/api)
factory-os/ ← factory operations dashboard (@brigid/factory-os)
energy/ ← energy management system (@brigid/energy-ms)
maintenance/ ← maintenance management (@brigid/maintenance-ms)
training/ ← training academy / LMS (@brigid/training-lms)
libs/brigid/
core/ db/ cross-domain/ sota-enhancements/ ← foundation
factory/ machines/ ai-industrial/ energy/ ← capability domains
maintenance/ robotics/ digital-twin/ cybersecurity/
weighing/ supply-chain/ training/ materials/
market-intel/ financials/
mining/ oil-gas/ packaging/ agricultural-mech/ ← verticals
water/ hvac/
Note three app package names differ from their directory names:
apps/brigid/energy is @brigid/energy-ms, apps/brigid/maintenance is
@brigid/maintenance-ms, apps/brigid/training is @brigid/training-lms — and
@brigid/energy-ms (app) is distinct from @brigid/energy (library).
Architectural Layers#
Brigid is organised in layers, each depending only on the layers below it.
Foundation — @brigid/core is the shared vocabulary. Its barrel
(libs/brigid/core/src/index.ts) re-exports nine modules: equipment,
maintenance, energy, robotics, security, business, units,
validators, standards, plus schemas. The type system is aligned to ISA-95,
IEC 61131-3, ISO 12100, IEC 61511, IEC 62443, ISA-18.2 and ISA-101. Identifiers
are plain string fields (equipmentId, sensorId, workOrderId) — there are
no branded ID types. @brigid/db is the Drizzle ORM schema for a dedicated
PostgreSQL database (TimescaleDB + pgvector). @brigid/cross-domain is the only
sanctioned exit point, and @brigid/sota-enhancements carries forward-looking
modules (edge AI, 5G remote ops, AR/VR, generative AI, RL, federated learning,
digital thread/quantum) over the same foundation contracts.
Capability domains — each library owns one industrial concern while sharing
the foundation contracts: @brigid/factory (line design + control-system
integration), @brigid/machines (phase-gate machine build),
@brigid/ai-industrial (vision, predictive maintenance, optimisation),
@brigid/energy, @brigid/maintenance, @brigid/robotics,
@brigid/digital-twin, @brigid/cybersecurity, @brigid/weighing,
@brigid/supply-chain, @brigid/training, @brigid/materials,
@brigid/market-intel, @brigid/financials.
Vertical industries — @brigid/mining, @brigid/oil-gas,
@brigid/packaging, @brigid/agricultural-mech, @brigid/water,
@brigid/hvac add domain-specific concepts on top of the core types and the
maintenance lifecycle; they extend, never replace, the shared foundation.
Applications — the five apps/brigid/* services compose libraries into
deployable workflows; the api service is the integration point for external
callers and partner domains.
The Foundation in Depth#
@brigid/core — type system, schemas, validators, standards#
equipment.ts defines the ISA-95 asset ladder (EquipmentLevel:
enterprise → site → area → production_line → work_cell → equipment_unit → control_module),
the base Equipment record, and specialisations (Machine, Sensor,
Actuator, PLC, SCADASystem/SCADAPoint, HMITerminal, ControlLoop,
ProductionLine, SafetySystem/SafetyInstrumentedFunction).
maintenance.ts, energy.ts, robotics.ts, security.ts, and business.ts
cover the work-order/calibration/spare-part, energy-asset, robot/twin,
OT-security/ training, and BOM/production/quality/market models respectively.
schemas.ts is where the contracts become enforceable. It ships Zod schemas
that reject malformed payloads at ingestion, and crucially encode domain
invariants as refinements, not just shapes:
OEEMetricsSchemarefinesoee === availability × performance × quality(within 0.001) — an OEE record that violates the identity cannot be stored.SensorSchema.tagis regex-validated against the ISA-5.1 instrument-tag pattern (/^[A-Z]{1,4}-\d{3,4}([A-Z])?$/, e.g.TT-101), andrangeMax > rangeMinis refined.CalibrationRecordSchema.measurementPointsrequires.min(3)("At least 3 calibration points required (ISO 17025)").ProductionOrderSchemarefinesplannedEndDate >= plannedStartDate;BatteryBankSchemarefinesusableCapacity <= nominalCapacity.
validators.ts is genuinely physics-based, not generic CRUD. It implements
validatePressureDrop (Darcy-Weisbach with a Churchill/Haaland friction factor
and laminar/transition/turbulent branching off the Reynolds number),
validateHeatTransfer (counter-current LMTD duty), validateElectricalLoad
(three-phase full-load current, NEMA voltage-imbalance derating, Ghana-ECG
power-factor penalty), and validateStructuralStress (σ = F/A against
yield/safety-factor). The data-quality half flags rather than drops bad
telemetry: checkSensorRange, checkRateOfChange, checkStuckValue,
checkSpike (modified Z-score over median absolute deviation), composed by
assessDataQuality into a good | suspect | bad verdict with diagnostic flags.
standards.ts is a real reference registry — IEC_STANDARDS, ISO_STANDARDS,
ANSI_ISA_STANDARDS, NFPA_STANDARDS, API_STANDARDS, ASME_STANDARDS, plus
GHANA_REGULATIONS — keyed and queryable via getApplicableStandards(domain).
@brigid/db — persistence schema#
libs/brigid/db/src/schema.ts defines the Drizzle tables and PostgreSQL enums
(brigid_equipment_status, brigid_equipment_level,
brigid_work_order_status, brigid_energy_source_type, brigid_robot_type,
brigid_security_level, brigid_certificate_status,
brigid_production_order_status, brigid_alarm_priority, and the two
maintenance enums). Worth noting: the persisted brigid_work_order_status enum
is the 13-value core lifecycle minus pending_approval — the
application/type layer carries one more state than the column. Tables cover
sites → factories → areas → lines → work-cells, equipment,
sensors/actuators/PLCs, work orders, spare parts, energy systems (solar arrays,
battery banks), water plants, robots/cells/programs, digital twins, security
assessments + vulnerabilities, training programs + certifications, materials
batches, and calibration records, wired with relations(...).
Four tables are time-series: brigid_sensor_telemetry (each row carries
value, unit, a quality flag, rawValue, source),
brigid_water_quality_readings, brigid_oee_records, and
brigid_condition_readings. These are declared as plain tables in Drizzle, then
converted to TimescaleDB hypertables via raw SQL in migrations.ts
(CREATE EXTENSION timescaledb; SELECT create_hypertable(...)). The same file
enables vector and adds an embedding vector(1536) column with an ivfflat
cosine index to brigid_ai_embeddings — pgvector isn't expressible through
drizzle-orm/pg-core directly, so it lives in the migration.
Capability Algorithms#
The capability libraries are where the domain depth lives. A representative sample, each grounded in real exported functions:
@brigid/factory—factory/src/production.tsimplementscalculateTaktTime,balanceLine(work-content distribution against takt),sizeBuffer,calculateOEE(six-big-loss decomposition),analyzeBottleneck,scheduleJobs(FIFO/SPT/EDD/CR/SLACK and a genetic dispatcher),runDESSimulation(discrete- event line model), andoptimizeLayout(A/E/I/O/U/X relationship-code SLP).factory/src/safety.tsis functional-safety engineering:performLOPA(layer-of-protection analysis to a residual SIL),calculateSIFPFDavgacross voting architectures (1oo1…2oo3),designSIF,generateProofTestProcedure,generateESDMatrix, andassessMachineRisk(ISO 13849 S/F/P risk graph).factory/src/scada.tscarries anAlarmManagementSystemclass (ISA-18.2 alarm state machine and flood/KPI analysis) and ISA-101 HMI screen/faceplate generation.@brigid/ai-industrial—ai-industrial/src/predictive-maint.tsis not a wrapper: it ships a radix-2 Cooley-Tukey FFT, bearing fault-frequency calculation (BPFO/BPFI/BSF/FTF), ISO 10816 RMS-velocity severity classification, anOilAnalysisPredictor(ASTM D-series thresholds), aMotorCurrentSignatureAnalyzer(broken-rotor-bar sidebands, eccentricity, RSH), aRemainingUsefulLifeEstimatorwith three real models (Wiener first-passage, Paris-law crack growth, Weibull survival), anAnomalyScorer(Mahalanobis distance with Gauss-Jordan covariance inversion + CUSUM), and aThermalImagingAnalyzer(BFS connected-component hotspot detection + OLS trend projection). Sibling modules cover computer vision, process optimisation, robotics AI, and edge AI.@brigid/maintenance—maintenance/src/kpi-analytics.tscomputes MTBF/MTTR and availability, benchmarks them, builds Pareto downtime breakdowns, ages the work-order backlog, and scores maintenance maturity.maintenance/src/spare-parts.tsimplementscalculateEOQ(withinverseNormalCDF/normalCDFfor service-level safety stock), VED and ABC classification, reorder evaluation, and part interchangeability.@brigid/energy—energy/src/solar.tsis Ghana-specific: aGHANA_MONTHLY_PSHirradiance table,SolarIrradianceAnalyzer,sizePVSystem,configureStrings,modelPVPerformance,analyzeShadingLoss, and technology-keyed degradation forecasting. BESS, grid-hybrid, and power-quality modules sit alongside.@brigid/robotics—robotics/src/robot-safety.tsimplements aSafetyZoneCalculator(ISO/TS 15066 speed-and-separation distances), aRobotRiskAssessment(ISO 13849), aCollisionDetectionSimulator(AABB/sphere), aRobotEnergyMonitor, aMultiRobotCoordinator, and an HRI workspace designer.
Component and Data Flow#
The path from raw sensor reading to operational decision, and out to partner domains, runs through the layers as follows:
- Telemetry arrives as REST batches; PLC/SCADA events arrive over the factory
WebSocket.
@brigid/corevalidates and enriches with industrial semantics (ISA-5.1 tags, OEE identity, data-quality flags) before anything is stored. - Relational records go to PostgreSQL tables; high-volume streams go to TimescaleDB hypertables, keeping ingestion off the transactional path.
- AI and vertical libraries consume stored telemetry to produce predictions, maintenance recommendations, and production decisions.
- App services expose approved state to dashboards and partner domains —
partner domains always through
@brigid/cross-domain, never via direct library imports.
Application Surface#
apps/brigid/api/src/app.ts builds a Hono application: secureHeaders, CORS,
logger, prettyJSON, a 100-req/min rate limiter on /api/*, and an
optional JWT middleware that populates an auth context if a Bearer token
is present (protected handlers call requireRole(); absent/invalid tokens leave
the context unset and are rejected downstream). Health lives at /health and
/ready; the functional API mounts at /api/v1 with route groups equipment,
telemetry, maintenance, energy, ai, training, and cross-domain.
telemetry.ts accepts batches of ≤1000 readings, validates each, and keeps them
sorted by timestamp (so out-of-order arrivals are inserted in time order,
not rejected), returning 202 when any reading is accepted. cross-domain.ts
exposes equipment-provision and maintenance-request POSTs that append
CrossDomainEvents (EQUIPMENT_PROVISION_REQUESTED,
CROSS_DOMAIN_MAINTENANCE_REQUEST) to a queue replayed over the
GET /api/v1/cross-domain/telemetry/subscribe SSE stream. websocket.ts
defines the FactoryWSMessageType union (SCADA_UPDATE, ALARM_ACTIVE,
ALARM_CLEARED, OEE_UPDATE, ASSET_STATUS_CHANGE, WORK_ORDER_UPDATE, plus
SUBSCRIBE/UNSUBSCRIBE/PING/PONG) and a createWebSocketHandler().
Two honest caveats at the app layer. First, the route handlers persist into
in-memory Map structures (telemetryStore, provisionRequests,
eventQueue) — the @brigid/db schema is the persistence target, but the API
routes are not yet wired to it. Second, the /ws/factory route currently
returns connection metadata (and 426 Upgrade Required on a raw upgrade); a
real WebSocket needs the @hono/node-ws adapter (createNodeWebSocket), which
the app does not yet mount. Both are real seams, honestly reported rather than
faked.
Persistence#
Brigid's design uses four storage technologies, each matched to an access
pattern: PostgreSQL for domain records, work orders, financials, and audit
history; TimescaleDB hypertables for telemetry and condition streams;
Redis for caches and hot dashboard state; and object storage for CAD
files, inspection media, robot programs (program_url is a MinIO reference),
and reports. The schema and migrations are implemented; the runtime wiring from
the app layer is the in-memory caveat above.
Cross-Domain Boundary#
@brigid/cross-domain is the single integration seam. Its barrel
(cross-domain/src/index.ts) exports five adapter families —
asase-integration.ts, freya-integration.ts, cybele-integration.ts,
saraswati-integration.ts, maat-integration.ts — each mapping Brigid DTOs
into a consumer-facing shape (e.g. Asase gets
food-processing/cold-chain/mechanization line designs; Maat gets
OEE/utilisation/RUL/energy analytics). cross-domain/src/api-contracts.ts holds
the Zod request/response schemas (BrigidEquipmentProvisioningRequest/Response,
BrigidEnergyIntegrationRequest, BrigidMaintenanceServiceRequest/Response,
BrigidTelemetryEvent, BrigidTrainingEnrolmentRequest,
BrigidCertificationRecord), all keyed by a requestingDomain enum of
asase | freya | cybele | saraswati | maat. The libs/brigid README also names
a @contracts/brigid package; the authoritative implemented contracts are the
ones in @brigid/cross-domain.
The boundary lets Brigid refactor its internal model without breaking consumers, and stops consumers depending on Brigid internals. Brigid owns the engineering control systems; consumers own their product economics — Cybele the built environment, Saraswati the technology products, Asase agricultural economics, Freya brand and design, Maat organisation-wide rollups.
Invariants, Failure Modes, and Extension Points#
Invariants (enforced in code, not aspiration): OEE must equal availability ×
performance × quality; sensor tags must match the ISA-5.1 pattern; calibration
records need ≥3 measurement points; production end-dates must not precede
start-dates; usable battery capacity must not exceed nominal. These live as Zod
refinements in core/src/schemas.ts and fail loudly on violation.
Safety and audit invariants (design-level, partly type-backed): workflows
touching safety-critical assets (robot cells, safety-instrumented functions,
control paths) carry deterministic fail-safe state —
SafetySystem.failSafeAction and bypassProcedure exist precisely to record
it; @brigid/factory's LOPA/SIF functions compute the protection layers and
PFDavg that back it. Calibration and maintenance records are intended to be
immutable after signoff, with corrections as append-only events.
Failure modes a maintainer must respect: telemetry ingestion tolerates
out-of-order and degraded-quality data (flagged, not dropped); the data-quality
validators classify rather than discard; the OEE/calibration schemas reject
inconsistent records outright rather than coercing them. Singular covariance in
the AnomalyScorer falls back to identity rather than producing NaNs. The app's
in-memory stores mean state is process-local and non-durable until the DB wiring
lands — do not treat the API as a system of record yet.
Extension points: a new vertical is a new libs/brigid/<name> package that
imports @brigid/core and the maintenance lifecycle and adds only its specific
types; a new shared concept is a type + Zod schema in @brigid/core (high blast
radius — every library imports core); a new external consumer is a new
*-integration.ts adapter plus contract schema in @brigid/cross-domain; a new
API capability is a route group mounted under /api/v1 in app.ts; forward-
looking capabilities land in @brigid/sota-enhancements over the same
contracts.
Status Summary#
Implemented: the @brigid/core type system, Zod schemas with domain
invariants, physics and data-quality validators, and standards registry; the
@brigid/db Drizzle schema + TimescaleDB/pgvector migrations; the capability
algorithms across factory, ai-industrial, maintenance, energy, robotics, and the
verticals; the @brigid/cross-domain adapters and contracts; the Hono API with
REST routes, the SSE cross-domain stream, and the WebSocket message model.
Planned / not yet wired: API persistence (routes use in-memory Maps; the
DB is the target); the live WebSocket upgrade (@hono/node-ws adapter not
mounted); a published platform-event catalog and the Kafka/MQTT/OPC-UA
transport; and the Rust/Python/WASM components named in the README. These are
labelled as seams here rather than presented as done.
Verification Expectations#
Changes run the affected packages' Vitest suites, type checks, linting, and contract checks, plus integration tests for affected app services. Industrial- safety, OT-cybersecurity, and control-path changes additionally require focused tests around validation, deterministic fallback behaviour, audit events, and permission boundaries — the areas where a silent error becomes a physical one.