Forge Platform
Industrial data operations for a manufacturing enterprise
Onboarding tutorial · two tracks from one landing fork · software-dev / contributor onboarding and an end-user overview of the framework.
Last verified: 2026-11-13 against the repository reh3376/forge at the merge of Pull Request (PR) 95 (branch main): every slide reviewed against the tree and the key documents (FB-114), the three-layer process control framework (D-11) added to both tracks.
Companions: README.md · docs/VISION.md · docs/WHERE-WE-ARE-GOING.md · docs/WHERE-WE-ARE.md · docs/ROADMAP.md · docs/PRINCIPLES.md · BACKLOG.md
Speaker notes
- Every substantive claim in this deck traces to one of the companion documents or to shipped code. The key docs are the source of truth; this deck is the guided path through them.
- Where something is not built yet, the deck says so. "Honest" sub-sections exist for that reason: the gap between the vision and the snapshot is the work.
- The deck is regenerated from
docs/tutorial.mdby tutorial-forge (scripts/tutorial-forge/); edit the source, not the HyperText Markup Language (HTML).
Choose Your Path
Two walkthroughs branch from here.
| Software Dev / Contributor Onboarding | End User Overview | |
|---|---|---|
| For | Engineers and technical PMs who will build on or inside Forge | Operators, supervisors and managers who will run a Forge site or decide from it |
| Depth | ~90 min, engineering-dense, code pointers throughout | ~45 min, plain language, no code required |
| Covers | contract, storage, governance, Operational Technology (OT) module and the three layers of process control, modules and Software Development Kit (SDK), context and curation, security, the contributor workflow, where we are | what Forge is for, how data flows, the hub you run, your systems as spokes, the plant floor and the layers of control above it, context and decisions, governance, screens, roles, operations |
| Next | Continue below ↓ (Contents → F1 Opening) | Jump to the End User path → |
Speaker notes
- The dev path is the default: keep scrolling. The end-user path is complete on its own and never sends an operator into the dev path for a topic.
- The left-margin sidebar lists every section and every diagram; clicking an acronym jumps to the glossary at the end, and a "Return to Previous" button brings you back.
Table of Contents
Software Dev Path: F1 Opening → F2 The Hub ↔ Spoke Contract → F3 Storage → F4 Spec-First Governance → F5 The Plant-Floor Module → F6 Modules, Module Builder, forge-display → F7 Context, Curation, Decisions → F8 Security, Identity, Federation → F9 Contributing → F10 Conclusion
End User Path: U1 Start Here → U2 How Data Flows → U3 The Hub You Run → U4 Your Systems as Spokes → U5 The Plant Floor → U6 Context, Products, Decisions → U7 Governance for Users → U8 Screens → U9 Identity, Roles, Credentials → U10 Operations → U11 Where to Go Next
| § | Section | Target | What you leave with |
|---|---|---|---|
| F1 | Opening: definition, thesis, the twelve problems, the finished system, honest state, the key docs | ~12 min | the shape of the platform and how to read its documents |
| F2 | The hub ↔ spoke contract: AdapterService, ContextualRecord, transport, ingest |
~12 min | what crosses the hub boundary and how |
| F3 | Storage: hub-owned databases, routing, migrations, Forge-issued credentials | ~8 min | where data lands and who may touch it |
| F4 | Spec-first governance (headline): the four layers, the Forge Test Specification (FxTS) family, hashing and the owner's approval | ~14 min | why nothing changes silently |
| F5 | The plant-floor module (forge-ot): tags, alarms, the write defense chain, changeover, one clock, the three-layer process control framework | ~15 min | how the plant floor is reached safely, and what will sit above the Programmable Logic Controller (PLC) |
| F6 | Modules, the module builder and forge-display | ~8 min | how new capability is built and shown |
| F7 | Context, curation and decisions | ~8 min | how a value becomes decision-quality |
| F8 | Security, identity and federation | ~6 min | roles, credentials, hub of hubs, repo posture |
| F9 | Contributing: setup, the workflow, the rules that bind, where things go | ~10 min | how to land a change |
| F10 | Conclusion: honest state, milestones, the decision queue, next | ~6 min | where to go from here |
Use the left-margin sidebar for section and diagram navigation.
Speaker notes
- F4 is the headline section for contributors: everything else either feeds a spec or is gated by one.
- Natural pauses: after F1's honest state, after F4's hashing rules, after F9's rules that bind.
F1 · Opening
Nav: ⇤ Table of Contents (TOC) · ⇅ Landing fork · F2 →
What Forge is, the thesis behind it, the twelve problems it is built to solve, what the finished system looks like, where it honestly stands today, and how to read its documents.
Speaker notes
- Source:
docs/VISION.md§1–§3,docs/WHERE-WE-ARE.md§1,docs/WHERE-WE-ARE-GOING.md§6.
What Forge Is
Forge is the industrial data operations platform for a manufacturing enterprise.
- It connects every operational system a plant runs on: Supervisory Control and Data Acquisition (SCADA)/PLC, Manufacturing Execution System (MES), Warehouse Management System (WMS), Computerized Maintenance Management System (CMMS), Enterprise Resource Planning (ERP), Quality Management System (QMS), historians, network management, lab and scanner devices.
- It turns their output into one governed record type with manufacturing context attached.
- It curates that into decision-quality data products with lineage and quality objectives.
- It renders every operator and management interface from declarative specifications.
- Its own management modules (forge-mes, forge-whs, forge-cmms, forge-ot, …) are optional: a site can run Forge purely as the integration and governance layer over the software it already has, or replace that software module by module.
Forge is also a governed engineering platform: contracts between components are machine-checked specifications with hash integrity and owner approval, so that neither people nor Artificial Intelligence (AI) coding agents can change an interface silently.
Speaker notes
docs/VISION.md§1 verbatim in substance. The vision is written in the present tense about a system that does not fully exist yet; the gap is the work.- Hub and spoke is the topology: the hub is
forge-core(src/forge), a spoke is any external system behind an adapter.
The Thesis
Bad manufacturing decisions come from missing quality, context and correlation, not from missing data.
| Forge is built so that… | which means |
|---|---|
| every datum is validated | quality codes travel with the value; a bad value is marked, not hidden |
| every datum carries where / when / what / who it belongs to | site, area, equipment, lot, shift, operator, work order, operating mode |
| any two data can be joined by that context | correlation is a query, not a project |
| the decision taken on it is itself recorded and measured | what was known, what was decided, what happened |
Poor decisions are far more costly than generally realised: the cost is spread across many units and shifts, and the root cause of a confidently wrong decision is rarely captured.
Speaker notes
README.md"What Forge Does" anddocs/VISION.md§1. The research basis (two BBD papers on information architecture and human judgment) is summarised indocs/PRINCIPLES.md§4.
The Twelve Problems
Each is stated as it is experienced in a plant; each has a component that carries it and a definition of solved (docs/VISION.md §2).
| # | Problem | What Forge does about it |
|---|---|---|
| P-1 | Every system is an island with its own data shape | hub and spoke: one contract, one record type |
| P-2 | Values arrive without context | context is declared per spoke and enforced at ingest |
| P-3 | Nothing can be trusted enough to decide on | curation with lineage and quality objectives |
| P-4 | SCADA and Human-Machine Interface (HMI) lock the plant to one vendor | an open OT module over Open Platform Communications (OPC)-UA; vendor software behind an integration module |
| P-5 | Integrations are one-off projects that rot | a module SDK and machine-checked contracts as Continuous Integration (CI) gates |
| P-6 | Writing to the plant floor is unsafe | a defense chain in the core for every write |
| P-7 | Contracts change silently, now also by AI agents | hash governance: every spec hashed, only the owner approves |
| P-8 | Every module ships its own User Interface (UI) | modules describe (FVTS), forge-display renders |
| P-9 | Decisions are not recorded, so their cost is never learned | the decision is a record with its products and lineage |
| P-10 | Multi-site enterprises break on the Wide Area Network (WAN) | a hub of hubs along ISA-95; sites keep working offline |
| P-11 | Credentials sprawl and nobody has a role model | the hub owns the databases and issues credentials; scoped roles |
| P-12 | There is no production deployment story | Kubernetes per hub; compose is development only |
Speaker notes
- Keep this table in mind through the deck: F2 carries P-1 and P-2, F3 P-11, F4 P-5 and P-7, F5 P-4 and P-6, F6 P-5 and P-8, F7 P-2, P-3 and P-9, F8 P-10 and P-11, F10 P-12.
The Finished System
| Layer of the hub | What it is when complete |
|---|---|
| Transport | forge.v1.AdapterService over gRPC Remote Procedure Calls (gRPC) with Transport Layer Security (TLS)/mutual Transport Layer Security (mTLS) both ways; push, pull, write-back, discovery |
| Ingest | validates manifest against the spoke's Forge Adapter Conformance Test Specification (FACTS) spec (hash verified), validates each record, routes, logs, feeds curation |
| Storage | hub-owned PostgreSQL, TimescaleDB, Neo4j, Redis; versioned migrations; modules never connect on their own credentials |
| Context Engine · Schema Registry | enrichment and the context field registry; versioned schemas and compatibility rules |
| Curation | normalization, data products, per-product pipelines, lineage, quality monitoring |
| Gateway · Hub Application Programming Interface (API) · Observer · Command-Line Interface (CLI) | auth and scoped Role-Based Access Control (RBAC); Representational State Transfer (REST) for operators and modules; health and SLOs; forge |
| Governance · Federation | the FxTS suite as CI gates with Forge Hash Test Specification (FHTS) hashing; hub of hubs |
Speaker notes
docs/VISION.md§3. The diagram is the finished system; F1's next sub-section says which boxes exist today.
Where We Are Today · Honest
From docs/WHERE-WE-ARE.md §1, the snapshot at PR 95:
- The hub ↔ spoke contract works end to end: a spoke registers, is checked against its FACTS spec, pushes records that are persisted, is pulled (Collect, Backfill, Subscribe) and receives write-backs, over TLS/mTLS both ways with per-spoke tokens.
- The OT module runs inside the hub with OPC-UA connections, a tag engine, ISA-18.2 alarms, the full control-write defense chain, and drives the MES changeover sequence including the PLC Common Industrial Protocol (CIP) runner. Since the one-clock steps of 2026-11-13 no record builder invents a source time, the OPC-UA server's clock is read and every stamp corrected by its measured offset, and every spoke declares how it is time-governed in its FACTS contract (FB-088, FB-094, FB-090).
- forge-mes is Go and not yet built: the imported NestJS backend and Next.js frontend stand in as the interim bridge and speak the spoke contract; the Go rewrite (FB-076) is decided and designed (
docs/decisions/forge-mes-go.md, signed 2026-11-03); the Go SDK scaffold is its first step. - Governance is real for four frameworks (FATS, FACTS, Forge Transport Test Specification (FTTS), Forge View Test Specification (FVTS)) plus FHTS hashing; the other seven are stubs or planned. forge-display does not exist yet; its contract (FVTS) does, with a runner and golden messages.
- Not yet: scoped roles in the gateway,
mod_mesin the hub, the Go module SDK, the hub-of-hubs federation, Kubernetes, and any management module in Go. - The three-layer process control framework (PC-L1 Proportional-Integral-Derivative (PID) in the PLC, PC-L2 Model Predictive Control (MPC), PC-L3 Subject-Matter Expert (SME) agents) is decided and signed by the owner (D-11, 2026-11-13); nothing of it is built, and nothing is built before its FSDs (F5).
| Measure | Value (2026-11-13) |
|---|---|
Python hub (src/forge) |
355 files, ~70,600 lines |
| Python tests | 267 files, 4,584 collected, full suite green on the locked dependency set |
Go (go/) |
32 files, ~10,100 lines; gofmt, go vet, go test gate CI |
Interim MES bridge (modules/Forge MES) |
~248,000 lines of TypeScript, kept until the Go forge-mes lands |
| Hub REST routes | 41 on the hub app, plus OT i3X (8) and OT control (16), plus the curation app |
| Storage migrations | 12 |
| FACTS specs · Forge API Test Specification (FATS) specs · FVTS specs | 9 · 28 · 1 |
| Backlog | 114 items recorded; every finding fixed or recorded |
Speaker notes
- Wording rule from the owner: the NestJS/Next.js code under
modules/Forge MESis "the interim MES bridge"; forge-mes is the Go module that FB-076 builds. Never "TypeScript forge-mes". - The numbers move with every push;
docs/WHERE-WE-ARE.md§2 is current before each one.
The Key Documents and How to Read Them
VISION.mdchanges only when a decision inROADMAP.md§1 changes.WHERE-WE-ARE-GOING.mdchanges when a milestone or the sequence changes.WHERE-WE-ARE.mdchanges before any push that changes the state it describes (rule since 2026-10-16).ROADMAP.mdholds decisions in force (A-1 … A-10, R-1 … R-19), the workstreams, the proposed sequence and the owner's decision queue (D-1 …).BACKLOG.mdis the unit of work: one item per PR; a finding is fixed or recorded, never skipped.PRINCIPLES.mdholds the design principles, technical invariants, the governance pattern, the decision frame, adapter tiers, technology choices and lessons that still bind.
Design records for decisions the owner must sign live in docs/decisions/ (roles.md, forge-mes-go.md, one-clock-ot-source-time.md, one-schema-registry.md, process-control-framework.md, all signed); an agent-facing context document accompanies the last in docs/personal/.
Speaker notes
docs/WHERE-WE-ARE-GOING.md§6 is the reading guide. A newcomer reads VISION once, GOING once, and WHERE-WE-ARE every time.
Repository Tour
| Path | What lives there |
|---|---|
src/forge/core |
ContextualRecord, decisions, adapters, manufacturing entities (ISA-95 hierarchy), the embedded Message Queuing Telemetry Transport (MQTT) broker, the context field registry, the schema-reference grammar, the clock helpers |
src/forge/transport · proto · proto_gen |
the gRPC hub and spoke sides, the proto set and the generated Python bindings |
src/forge/ingest |
the ingest pipeline, the FACTS check at Register, receipt stamping |
src/forge/storage |
router, factory, engines (PostgreSQL, TimescaleDB, Neo4j, Redis), access control, migrations |
src/forge/context · registry · curation |
Context Engine, Schema Registry, curation (normalization, data products, pipeline, lineage, quality) |
src/forge/governance |
FxTS: schemas, runners, specs, the shared hashing runner |
src/forge/gateway · api · observer · cli |
auth and RBAC middleware, the hub FastAPI app, health, the forge CLI |
src/forge/modules/ot |
the OT module: OPC-UA client, tag engine, alarming, control, MQTT, bridge, i3X, changeover |
src/forge/sdk |
the module builder and the scripting SDK (forge.* namespace) |
src/forge/adapters |
the eight in-repo spoke adapters (whk-wms, forge-mes, whk-cmms, whk-erpi, whk-nms, bosc-ims, next-trend, scanner-gateway), each with its manifest and config, and four generic adapter stubs |
go/ |
Go models mirroring the core models, the scaffold, generated bindings, daemon and CLI stubs |
modules/Forge MES |
the interim MES bridge (NestJS + Next.js) that FB-076 retires |
tests/ |
267 files mirroring src/; migration tests read the migration source |
docs/ |
the key docs, FxTS/ framework pages, decisions/, deployment/ (clock discipline), governance/, core/, spokes/, p7-ot-module/, personal/ (agent context) |
deploy/docker |
the development compose stack and the hub image |
Speaker notes
F1 Recap → F2
- Forge: one governed record type, context attached, curated into data products, interfaces rendered from specs, contracts hashed and owner-approved.
- Twelve problems, each carried by a named component with a definition of solved.
- Today: the contract works end to end, the OT module runs in the hub, governance is real for four frameworks; forge-mes in Go, forge-display, scoped roles, federation and Kubernetes are not built.
- Read VISION once, GOING once, WHERE-WE-ARE every time.
Next: what actually crosses the hub boundary.
F2 · The Hub ↔ Spoke Contract
Nav: ← F1 · ⇤ TOC · ⇅ Landing fork · F3 →
One contract, forge.v1.AdapterService, carries everything between a spoke and its hub. This section covers the twelve RPCs, the one record type, the transport, and what happens at Register and at Ingest.
Speaker notes
- Source:
docs/VISION.mdP-1,docs/WHERE-WE-ARE.md§3.1,src/forge/proto,src/forge/transport,src/forge/ingest.
AdapterService · Twelve RPCs
| Group | RPC | Direction | Purpose |
|---|---|---|---|
| Lifecycle | Register |
spoke → hub | present the manifest; the hub checks it against the spoke's FACTS spec (hash verified) before accepting |
| Lifecycle | Configure, Start, Stop, Health |
hub → spoke | configure and run the adapter; report health, including clock offset |
| Push | Ingest |
spoke → hub | stream ContextualRecords; persisted and FACTS-checked |
| Pull | Collect, Backfill |
hub → spoke | on-demand reads and historical ranges |
| Pull | Subscribe, Unsubscribe |
hub → spoke | live streams of changes |
| Write-back | Write |
hub → spoke | a session-bound callback into the source system |
| Discovery | Discover |
hub → spoke | enumerate what the source exposes |
- Compiled protobuf over gRPC; JavaScript Object Notation (JSON) over gRPC is forbidden (decision A-1).
- Go and Python bindings generated from one proto set (
src/forge/proto,src/forge/proto_gen,go/gen/forge). - Spokes are Python inside the hub or external processes in any language that speaks the proto.
Speaker notes
- The rule "spokes never talk directly to each other" holds: every exchange goes through the hub. Spokes may publish to the Forge broker for real-time data, but the contract is the hub's.
ContextualRecord · The One Record Type
RecordContextcarries the context field registry slot for slot, on the proto and in Go, with every producer and the TimescaleDB table following (FB-013).- A naive datetime or an offset-less string is rejected at the model (
forge.core.clock, FB-014); ruff'sDTZrules block CI. - The hub stamps
ingestion_timewith its own clock on receipt; the spoke's stamp is kept assent_time; nothing is invented (FB-087). - No record builder invents a source time either: a value without a source stamp is refused unless its connection declares
source_timestamp_origin: forge; then Forge's read time stands in and the record says so (source_clock,source_uncertainty_seconds), and the refusal is on health, status, API and CLI (FB-088, 2026-11-13). - Every schema reference uses one grammar,
forge://schemas/<spoke>[/<Entity>][/v<version>], held at every boundary (FB-008).Speaker notes
- The context field registry (
src/forge/core/registry) and the manufacturing entity catalog (docs/core/manufacturing-entity-catalog.md) define what each slot means, so "area" is the same thing in every spoke. sent_timebecomesspoke_timeunder the one-clock design (D-9, signed 2026-11-03) when the hub-to-spoke time exchange lands (FB-092).
- The context field registry (
Transport · gRPC, TLS/mTLS, Tokens
| Property | State | Where |
|---|---|---|
| TLS / mTLS hub → spoke and spoke → hub | ✅ | FB-063, FB-072 |
| Per-spoke callback token, scoped hub endpoints | ✅ | FB-063 |
| Hub → spoke write-back over a session-bound callback | ✅ | FB-054 |
| Durable adapter registry and ingest log | ✅ | FB-060, migration 007 |
| FTTS transport spec and runner | 🟡 | specs/grpc-hardened-transport.ftts.json; no docs/FxTS/FTTS.md page yet |
| Transport parity tests for the Go module | ⬜ | FB-055 |
| Hub time in the contract; fail-closed clock enforcement | ⬜ | FB-092, FB-093 (D-9 signed 2026-11-03) |
Code: src/forge/transport/grpc_server.py (hub), spoke_client.py (spoke side), grpc_channel.py (retry), proto_bridge.py (proto ↔ model), transport_adapter.py (adapter base).
Speaker notes
Ingest · What Happens at Register and at Ingest
forge.ingest.facts_checkverifies the spec's hash before trusting it; a spoke whose manifest or hash does not match is refused.- One hub-clock reading per batch (
IngestPipeline.ingest→stamp_receipt). - Every link's clock offset is measured and exposed on
AdapterHealth.clock,GET /v1/ingest/stats, the OT connection status and OpenTelemetry (forge.clock.offset,forge.clock.out_of_tolerance); the provisional tolerance is 1 s (FB-089). Enforcement is FB-093 (D-9 signed 2026-11-03: per-link tolerance classes, never silent). - Curated records are persisted with the raw ones (FB-009).
Speaker notes
HubIngestServicerreplaced the original in-memory servicer (FB-053); before that, records were queued and never routed.- Push persisted and FACTS-checked at Register since FB-053; pull since FB-061 and FB-071.
Pull, Backfill and Write-back
- Collect: the hub asks a spoke for records on demand (bounded by the spoke's declared capabilities).
- Backfill: historical ranges, used by historian spokes and the forge-mes
AuditLogbackfill (FB-071). - Subscribe / Unsubscribe: live change streams.
- Write: the hub writes back into a source system through a session-bound callback; the source's own rules still apply, and in the OT module the write first passes the defense chain (F5).
Everything a spoke can do is declared in its FACTS spec (capabilities, data_sources, error_handling); the runner checks the declaration, and Register checks the manifest against it.
Speaker notes
- Capability declarations are the contract's vocabulary: a spoke that is
INGESTIONonly cannot be written to; one that isBIDIRECTIONALmust handle write errors as its spec says.
F2 · Honest State
| Gap | Backlog |
|---|---|
| FTTS has no documentation page | noted in docs/WHERE-WE-ARE.md §3.1 |
| Go transport parity tests | FB-055 |
| Hub time in the contract; refusing an out-of-tolerance clock | FB-092, FB-093 (D-9 signed 2026-11-03) |
The spoke's time fields (sent_time, source time per spoke) |
FB-088 done 2026-11-13 (source_clock, source_uncertainty_seconds); FB-090 done 2026-11-13 (the FACTS time_governance declaration) |
| Generic adapters (csv_file, mqtt_sparkplug, opcua, rest_generic) | package stubs only |
Next: where the records land.
F3 · Storage and the Hub-Owned Databases
Nav: ← F2 · ⇤ TOC · ⇅ Landing fork · F4 →
The hub owns the databases (decision A-6). This section covers the engines, routing, the twelve migrations, Forge-issued credentials, the "observe → shadow → own" path for module data, and the two schema registries.
Speaker notes
- Source:
docs/PRINCIPLES.md§2 and §6,docs/WHERE-WE-ARE.md§3.3,docs/DB_ORCHESTRATION_FRAMEWORK.md,src/forge/storage.
The Hub Owns the Databases (A-6)
| Store | Role | State |
|---|---|---|
| PostgreSQL 16 | relational: forge_core (adapters, ingest log, permissions, audit, registries), forge_canonical (data products), one mod_<name> schema per module |
in force |
| TimescaleDB | time series: forge_ts.contextual_records, one column per RecordContext slot |
in force |
| Neo4j 5 | lineage and topology | in force |
| Redis | cache and sessions | in force |
| RabbitMQ · MQTT | module events (the wh.whk01.distillery01.* proto-UNS); the embedded MQTT 3.1.1 broker |
in force |
| MinIO · Kafka | object store; the enterprise bus when volume requires it | in the compose stack; Kafka planned |
- Modules hold only Forge-issued credentials and never connect on their own.
- Storage is polyglot by invariant: record types route to the engine that fits them; no single database serves every access pattern.
- Serving is API-first: consumers go through versioned APIs defined by FATS specs, never to a database directly.
Speaker notes
- The hub's health orchestrator probes all seven compose-stack components (
/v1/health,/readyz, FB-006).
- The hub's health orchestrator probes all seven compose-stack components (
Routing
forge.storage.factorybuilds the engines from configuration; the router picks the engine per record.- Today the routing registry is in memory and empty on every start, so routing falls through the default routes by
data_type. That is the subject of the one-schema-registry design record (D-10, below).Speaker notes
forge.storage.engines.timescalewrites everyRecordContextslot (FB-013); the migration test holds the writer's column list equal to the table's.
Migrations · Twelve, and the Runner
| # | Creates |
|---|---|
| 001 | forge_core schema: adapters, records log, governance reports, schema entries |
| 002 | the six spoke schemas mod_wms … mod_ims and their roles, created NOLOGIN without a password (FB-099) |
| 003 | forge_canonical (data products) |
| 004 | TimescaleDB initialisation |
| 005 | lineage tables |
| 006 | forge_ts.contextual_records (the table the engine writes); its downgrade removes the schema (FB-101) |
| 007 | durable adapter registry and ingest log |
| 008 | module_permissions and access_audit (replaces two 001 tables, FB-003) |
| 009 | Schema Registry and equipment tables |
| 010 | the data product curation spec column |
| 011 | one column per RecordContext slot on contextual records |
| 012 | closes the placeholder login on spoke roles that 002's earlier text created, unless Forge issued the role |
forge migrate up | status | down
python -m forge.storage.migrations.run up --target postgres # the runner behind the CLI
- Online runs go through asyncpg on SQLAlchemy's async engine (FB-003).
- The whole downgrade runs in one transaction; head → base → head is verified clean on a throwaway TimescaleDB container (FB-098, FB-101).
tests/storage/test_migrations.pyreads the migration source and holds it to the models and the writers.Speaker notes
- A migration is never edited after it has been applied somewhere; a repair is a new revision (012 is the pattern).
- Postgres and the time-series target share the chain; the hypertable step runs only when the timescaledb extension is present.
Forge-Issued Credentials · forge db access
forge db access grant forge-mes mod_mes --level write
forge db access grant forge-mes forge_canonical --level read
forge db access issue forge-mes --host localhost # prints DATABASE_URL=... once
forge db access list | revoke ...
- A spoke role (
forge_mod_<x>) has no way in untilissuerunsALTER ROLE … WITH LOGIN PASSWORDwith a password Forge generated; re-issuing rotates it. - The password is shown once and never stored; the grant, the issue and every refusal are written to
forge_core.access_audit(FB-003, FB-057 step 1). - READ: usage and select, now and by default on future tables. WRITE: also insert, update, delete and sequences. ADMIN: also create on the schema (the interim MES bridge runs its own Data Definition Language (DDL) through Prisma until the hub owns that DDL).
- Protected schemas (
forge_core,forge_canonical,curated,lineage) cannot be granted for writing.Speaker notes
PersistentAccessControlleris the in-memory controller with every change written to the store the moment it is made; the storage factory and the CLI share it.- Open: the bootstrap read grant on
forge_corecovers only the four tables that existed at 002 (FB-100, decided with FB-057 step 2).
Observe → Shadow → Own
- The hybrid path from
docs/DB_ORCHESTRATION_FRAMEWORK.md: adapters read spoke databases, a shadow writer mirrors into the hub, ownership transfers per module. - Step 1 (grants and issued credentials) is delivered; steps 2–5 (the MES data into
mod_mes) follow the forge-mes Go design, signed 2026-11-03 (FB-057, D-3). forge.storage.shadowandforge.storage.backfillare the shadow writer and the historical backfill.Speaker notes
- "Own" is the end state for every management module: the module's schema lives in the hub's PostgreSQL and the module never carries a password it created itself.
Two Schema Registries · D-10
F20 Schema Registry (forge.registry) |
Routing registry (forge.storage.registry) |
|
|---|---|---|
| Served at | /v1/schemas (9 routes), Postgres tables from migration 009 |
in-memory only; the schema_entries table from 001 is never written |
| Models | SchemaMetadata, SchemaVersion, integer versions, compatibility mode |
SchemaEntry with engine, namespace, retention, authoritative spoke, status |
| Effect | the registry the hub exposes | empty on every start, so routing uses the default routes |
The design record docs/decisions/one-schema-registry.md (round 1 2026-10-26, signed 2026-11-03) folds routing into the F20 registry as a placement facet: ten proposals, eight questions answered by the owner one at a time, eight implementation steps, one PR each (FB-097, D-10).
Speaker notes
- This is the pattern for every design the owner must sign: a record with a status line, statements tagged [OWNER] / [FACT] / [PROPOSED] / [OPEN], numbered proposals and questions with proposed answers. Nobody signs on the owner's behalf.
F3 · Honest State
| Gap | Backlog |
|---|---|
mod_mes in the hub (MES data moves in) |
FB-057 steps 2–5, in the signed forge-mes Go design's step order (D-3) |
| Backups and a restore procedure | no backlog id yet |
| The two registries converge | FB-097 (D-10) |
Bootstrap read grant on forge_core partial |
FB-100 |
Next: the headline section, governance.
F4 · Spec-First Governance
Nav: ← F3 · ⇤ TOC · ⇅ Landing fork · F5 →
The spec is the contract. This section is the headline for contributors: spec-first governance, the four layers every framework shares, the family of frameworks and their state, hashing and the owner's approval, the anatomy of a FACTS spec, and how to run the gates.
Speaker notes
- Source:
docs/PRINCIPLES.md§3,docs/FxTS/README.md,docs/governance/facts-developer-guide.md,docs/WHERE-WE-ARE.md§3.9,src/forge/governance.
Spec-First, Not Test-First
- The spec defines what must exist and how it must behave; the implementation serves the spec; the runner enforces conformance; the CI gate blocks deviation.
- A FATS spec that says
GET /v1/data-products/{id}returns 200 with a given shape is a prior commitment, not a test of an existing endpoint. - Drift is caught by the runner; a spec change is a visible diff in review.
- A behavioural change is a spec change, and a spec change is reviewed. No specification field is silently ignored.
Rules carried over from Multi-Dimensional Emergent Memory Graph (MDEMG)'s UxTS and confirmed in practice:
- A spec with zero assertions fails; it does not pass (the "0/0 problem").
- Parity: schema fields the runner does not enforce are reported, never ignored; a single unimplemented field is a hard fail.
- Runners produce structured verdicts with check IDs, spec references, violation details and timing, not bare pass/fail.
The Four Layers
| Layer | Where |
|---|---|
| Schemas | src/forge/governance/<framework>/schema/*.schema.json |
| Specs | src/forge/governance/<framework>/specs/*.json (FACTS: nine, one per spoke) |
| Runners | src/forge/governance/<framework>/runners/, over the shared runner in forge.governance.shared.runner (hashing, verification, approval) |
| Gate | the hub-python CI job runs the governance tests; forge governance run is the operator's path |
Speaker notes
- Hard fail blocks merges; soft fail warns. No framework is advisory-only.
The Family
| Framework | Governs | State (2026-11-13) |
|---|---|---|
| FATS · Forge API Test Specification | API contracts: routes, shapes, status codes | schema + runner + 28 specs, one per hub-served route |
| FACTS · Forge Adapter Conformance Test Specification | identity, capabilities, lifecycle, connection, data contract, context mapping, error handling, time governance | schema + runner (facts:schema-valid + 35 rule checks, facts:time-governed among them since FB-090) + 9 specs, every hash owner-approved; 8 validate |
| FTTS · Forge Transport Test Specification | TLS, tokens, streaming behaviour | schema + runner + 1 spec; no doc page |
| FVTS · Forge View Test Specification | module ↔ display: points, alarms, actions, surfaces, profiles | schema + 19-check runner + reference renderer + golden messages + 1 spec |
| FHTS · Forge Hash Test Specification | hash integrity and owner approval of every spec above | hashing, verification, approval, revert, registry |
| Forge Quality Test Specification (FQTS) · Forge Security Test Specification (FSTS) | data quality · security controls | stubs |
| Forge Data Test Specification (FDTS) · Forge Lineage Test Specification (FLTS) · Forge Normalization Test Specification (FNTS) · Forge Observability Test Specification (FOTS) · Forge Performance Test Specification (FPTS) | schema evolution · lineage · normalization · observability · performance | planned (doc pages only) |
Governance is declarative by invariant: quality, lineage, normalization and security rules are specifications, not code paths.
Speaker notes
FHTS · Hashing and the Owner Approval
- Every governed spec carries an
integrityblock:spec_hash,hash_state,previous_hash,approved_by,approved_at,change_historynaming who or what changed it. - The content hash excludes the whole
integrityblock (a history entry refers to the hash itself); canonical JSON uses sorted keys, compact separators and ASCII escaping, so the digest is portable. - Hash verification is independent of assertion execution: a spec can pass every assertion and still have
hash_verified=falseif it was modified. Two orthogonal signals. - Only the owner approves a spec hash. Agents re-stamp to
pending_reviewand never approve on the owner's behalf.approveis refused when the hash no longer covers the content. - The hub's Register check verifies a spoke's FACTS hash before accepting the spoke.
A FACTS Spec, Anatomically
| Block | Declares |
|---|---|
adapter_identity |
id, name, version, tier (OT, MES_MOM, ERP_BUSINESS, HISTORIAN, DOCUMENT), type (INGESTION, BIDIRECTIONAL, WRITE_ONLY, DISCOVERY_ONLY) |
capabilities |
what the spoke can do: ingest, collect, backfill, subscribe, write, discover |
connection |
parameters, protocols, timeouts, retry policy |
data_sources |
each source the spoke reads or writes (GraphQL, REST, RabbitMQ, MQTT, gRPC, database, WebSocket …), with its schema reference |
context_mapping |
source field → Forge context field, and the enrichment rules the hub applies |
error_handling |
dead-letter policy, retry classes, what is fatal |
time_governance |
how the spoke is time-governed (one clock, FB-090): time source, sync protocol, clock-read method, probe cadence, which clock stamps its values, tolerance class, fail_closed: true, per-connection entries; required, checked by the blocking facts:time-governed |
sample_records |
records the runner validates against the data contract |
integrity |
the FHTS block |
- Nine specs today: whk-wms (the reference), forge-mes, bosc-ims, whk-cmms, whk-erpi, whk-nms, next-trend, scanner-gateway, ot-module.
- The runner validates every spec against the JSON schema first (
facts:schema-valid) and reads its enums from the schema (FB-080). - The developer guide,
docs/governance/facts-developer-guide.md, walks the schema, how to write a spec, running the runner, common failures and cross-spoke consistency.
Running the Gates
forge governance specs # every spec's hash state, approver, hash still verifies?
forge governance specs --pending # what awaits the owner
forge governance validate-spec <spec.json> # against its framework schema
forge governance run facts whk-wms # one framework, one spec; exit 1 on any failure
forge governance stamp <spec.json> # after an edit: history entry, pending_review, no approver
forge governance approve <spec.json> --by reh3376 # the owner, on their own word, never on their behalf
runcovers FATS, FACTS, FVTS and FTTS (FB-021, FB-083).- The hub test suite holds FATS in both directions: every served route has a spec, every spec names a served route.
- The FVTS runner has a render-profile baseline and golden messages; a module can only tighten the baseline, never loosen it.
F4 · Honest State
| Gap | Backlog / decision |
|---|---|
| The time-governance declaration is in place; refusing a clock outside its class is not | FB-093 (D-9) |
The OT FACTS spec fails facts:schema-valid and eight vocabulary checks |
FB-079, D-8 |
| FQTS and FSTS are stubs; FDTS, FLTS, FNTS, FOTS, FPTS are planned | M5 |
| FTTS has no documentation page | noted in docs/WHERE-WE-ARE.md §3.9 |
The OT reference FVTS spec uses invented points and is pending_review |
FB-078 |
Next: the module that reaches the plant floor.
F5 · The Plant-Floor Module (forge-ot)
Nav: ← F4 · ⇤ TOC · ⇅ Landing fork · F6 →
forge-ot is the most mature module and lives in this repository. This section covers the tag engine, ISA-18.2 alarming, the control-write defense chain, the MES changeover, the scripting SDK, the Ignition bridge, the one-clock principle, and the three-layer process control framework the owner decided on 2026-11-13 (D-11).
Speaker notes
- Source:
docs/VISION.mdP-4 and P-6,docs/WHERE-WE-ARE.md§3.5,README.md"OT Module",src/forge/modules/ot,docs/PRINCIPLES.md§2 (one clock),docs/decisions/process-control-framework.md(D-11).
What It Is
- A thin, open wrapper over OPC-UA: asyncua owns the wire protocol (pinned
==2.1.0, FB-085); Forge owns tags, alarms, writes, scripting and history. - Hosted inside the hub with PLC connections, supervision and liveness (
forge.modules.ot.host, FB-069, FB-070). - Replaces the vendor SCADA/HMI layer (Ignition) problem by problem: tag engine, alarming, scripting SDK, i3X-shaped REST, MQTT; where a site keeps its vendor product, the Ignition bridge runs a read-only parallel validation.
- HMI/SCADA itself is an optional module activated per site (decision A-4); forge-display renders the surfaces (A-3).
| Subsystem | Package |
|---|---|
| OPC-UA client, path normalisation (OPC-UA ↔ Ignition ↔ Forge) | opcua_client |
| Tag engine: definitions, registry, User-Defined Type (UDT) templates, persistence, eight provider types | tag_engine |
| ISA-18.2 alarming: state machine, detector, engine, integrations, API | alarming |
| Control writes: validation, review, interlocks, authorization, write engine, audit, recipe integration | control |
| MQTT: publisher, subscriber, tag publisher, topic router, Sparkplug B, rate limiter | mqtt |
| Ignition bridge: adapter, REST client, tag mapper, dual-write validator, health dashboard | bridge |
| i3X (CESMII) models and router; context resolvers; store-and-forward; acquisition | i3x, context, acquisition |
Speaker notes
- Phases 1–6 of the OT plan are complete (
README.md"Phase Summary"); phase numbering history is indocs/ROADMAP.md§7.
Tags and Providers
| Provider | Serves |
|---|---|
opcua_provider |
direct OPC-UA reads |
acquisition |
scheduled polling |
memory_provider |
in-memory tags |
expression_provider |
calculated tags |
query_provider |
Structured Query Language (SQL)-driven tags |
virtual_provider |
virtual and derived tags |
event_provider |
event-driven tags |
base |
the provider protocol |
TagDefinition,TagValue,QualityCode,DataTypeare the models; every value carries quality.- Context resolvers attach site, area, equipment, lot, shift and mode to OT records; the batch context resolver wired to MES is open (FB-020).
Alarms · ISA-18.2
- Seven-state ISA-18.2 machine, nine alarm types (HI, HIHI, LO, LOLO, digital, rate-of-change, quality, communication, custom).
- Event-sourced journal; REST under
/alarms(active, history, config, ack, shelve). - Integrations: MQTT publish, RabbitMQ fan-out, CMMS auto work orders.
Speaker notes
- Alarm presentation (annunciation, priority colours, staleness) is forge-display's job from the FVTS spec, not the module's.
Control Writes · The Defense Chain (A-7)
- Safety stays in the core: roles, interlocks, confirmation, read-back and audit are enforced in forge-core/OT, never only in a UI.
- Server-side two-step review with reason codes and
REJECTED_REVIEWsince FB-074; multi-party approval follows the role model (D-1, signed 2026-11-03; FB-075). - The audit record goes to the hub store and to an external publisher (FB-066, FB-067).
- The FVTS contract binds every UI action to a required role, a confirmation mode and the statuses it must handle; the render profile decides whether a surface may write at all.
Speaker notes
- "Solved when": no path exists from any interface to a PLC that does not pass the chain, and every write is reconstructible from the audit log (
docs/VISION.mdP-6).
- "Solved when": no path exists from any interface to a PLC that does not pass the chain, and every write is reconstructible from the audit log (
The MES Changeover
- The orchestrator runs the changeover sequence against the PLC through the CIP runner, with recipe integration turning an MES recipe into batched PLC writes through the defense chain (FB-062, FB-065).
- REST endpoints for confirm-start, retry-recipe, resume and connection restart sit behind the hub's
adapters:writescope; the hub user is the actor on the MES write, the audit record and the events (FB-082).
| Capability | State |
|---|---|
| Orchestrator, CIP runner, recipe integration, REST | ✅ |
| Endpoints behind a hub scope | ✅ FB-082 |
| Batch context resolver wired to MES | ⬜ FB-020 |
Speaker notes
The Scripting SDK · forge.* Replaces system.*
| Module | Replaces | Key functions |
|---|---|---|
forge.tag |
system.tag.* |
read, write, browse, get_config, exists |
forge.db |
system.db.* |
query, named_query, transaction, scalar |
forge.net |
system.net.* |
http_get, http_post, http_put, http_delete |
forge.alarm |
system.alarm.* |
get_active, ack, trigger, shelve, get_history |
forge.log · forge.date · forge.dataset |
system.util.getLogger, system.date.*, system.dataset.* |
logging, date handling with Java → Python pattern conversion, tabular data |
forge.perspective · forge.file · forge.util · forge.security |
system.perspective.*, system.file.*, system.util.*, system.security.* |
UI interaction, sandboxed files, JSON and messaging, user and role queries |
- Python 3.12+ engine replacing Jython 2.7: discovery, loading, hot reload; a PEP 302 import allow-list sandbox;
@timer,@on_tag_change,@api.routetriggers; area and tag-pattern RBAC; an append-only audit ring buffer. - The migration map covers all 52
system.*calls; 42 Tier 1 scripts are identified for conversion (docs/p7-ot-module/).
One Clock, Governed by the Hub
The owner's principle (2026-10-18): records from different sources only reconcile if their timestamps come from the same master time.
| Rule | State |
|---|---|
| Every stored timestamp is UTC and timezone-aware; naive rejected at the model | ✅ FB-014 |
| The hub stamps receipt with its own clock | ✅ FB-087 |
| The offset of every connected clock is measured, recorded and surfaced | ✅ FB-089 (provisional 1 s tolerance, warning only) |
A tag's source_time is device time corrected to master by the device's measured offset, original stamp and offset recorded |
🟡 FB-088 done 2026-11-13 (no invented stamp; the stamping clock named once declared); FB-094 steps 2 and 3 done 2026-11-13 (the server's clock is read on every OPC-UA response and on a runtime probe cadence, and the source and server stamps are corrected by its filtered offset at the spoke, the stamp as sent, the offset and the time quality kept); step 6 done too (every tag declares max_sampling_uncertainty_ms, refused at load when the acquisition cannot meet it; the bound is on every value), so FB-094 is complete for what the tree has; FB-090 done 2026-11-13 (the FACTS declaration); design record docs/decisions/one-clock-ot-source-time.md signed 2026-11-03 |
| Hub time in the contract; a hub, module or spoke outside tolerance is refused | ⬜ FB-092, FB-093 (D-9 signed 2026-11-03) |
| Per-spoke declaration of time governance; a quality dimension for time | 🟡 FB-090 done 2026-11-13 (FACTS time_governance: clock origin, probe cadence, tolerance class, fail closed); FB-091 (the quality dimension and the offset assumed on an offset-less stamp) |
Speaker notes
- The OPC-UA converter stores
SourceTimestampas the server sends it and, since FB-088 (2026-11-13), invents nothing when it is absent: the value is refused unless the connection declares originforge. Since FB-094 steps 2 and 3 (2026-11-13) the server's clock is read on every response and on the probe cadence, keyed by the clock measured, and each stamp is corrected by that clock's filtered offset where it enters, the stamp as sent and the offset kept on the record. That row is marked 🟡 deliberately: the principle says a device whose clock cannot be read is not a valid source. - D-9 chooses among established standards: Network Time Protocol (NTP)/chrony strata mirroring the hub hierarchy, Precision Time Protocol (PTP)/IEEE 1588 on the plant network, NTP four-timestamp measurement in-band, IEC 61850-5 tolerance classes, IEC 61850
TimeQualityand OPC UADataValuefields on the record. - The deployment requirement (the NTP/PTP chain from the top hub, the tolerance classes, what fails closed, a new-site checklist) is
docs/deployment/clock-discipline.md(FB-090).
Three Layers of Control · PC-L1 / PC-L2 / PC-L3 (D-11)
- New, not the classic control hierarchy (owner, F-2): portions of layers 1 and 2 have run in industry for years; the whole, with PC-L3 and the autonomy model, has not. The distillery's seven batch processes are an example only; the framework is for every industry Forge serves (F-6).
- One vocabulary for PID and MPC: Process Variable (PV) (the variable controlled), Setpoint (SP) (its target), Manipulated Variable (MV) (what the controller moves), Disturbance Variable (DV) (a disturbance); "CV" is retired because it means two different things (V-1 to V-4). Logix
PIDE.CVmaps to MV at the PLC boundary. - PC-L2's two goals: consistent control of a complex loop, and predicting disturbances to act before they manifest (F-3); it improves its own model and tuning (F-4) under the autonomy model on the next slide.
- Strict adjacency (H-1): PC-L3 reaches PC-L1 only through PC-L2; if PC-L2 is offline, PC-L3 writes recommendation logs only (H-8).
Speaker notes
- Source:
docs/decisions/process-control-framework.md§1, §2.1 and §2.2, with the companion context indocs/personal/. The layers are named PC-L1/2/3 so they cannot be confused with the reference architecture's L1–L5 or with ISA-95 levels (V-5).
- Source:
What Never Changes, and How Autonomy Is Earned
| # | Hard invariant (no setting, rollout profile or earned autonomy relaxes it) |
|---|---|
| H-1 | each layer affects only the layer directly below it |
| H-2 | no PLC code is generated or edited on a PLC; recommendations only, an engineer writes the logic |
| H-3 · H-4 | no layer writes to safety systems; none forces, bypasses or overrides an interlock or permissive |
| H-5 | PLC-side clamps range- and rate-check every value PC-L2 writes |
| H-6 | the operator can always take a loop out of MPC mode, immediately, from the plant's own HMI (UI-1) |
| H-8 | PC-L2 offline: PC-L3 knows it, cannot effect change, writes recommendation logs only |
- Every PC-L2 self-improvement category (model parameters, tuning, model structure, operating limits) and every PC-L3 action type (targets; limits and priorities; controller configuration; schedule requests) is Off, Propose or Autonomous; everything ships Off (AU-1, L2-10, L3-4).
- Autonomy is earned per category: four confidence signals (prediction accuracy, the outcome of promoted changes, the human agreement rate, shadow-run performance), each over its own threshold, for a duration and a minimum number of evaluated events; the framework ships no values, a user enters them; a person grants the switch by default; revocation is automatic (AU-3 to AU-9).
- Changes are versioned and validated by a backtest plus a shadow run; rollback is a default an administrator may adjust, and without it a category is Propose at most (AU-10 to AU-16). Shed: heartbeat bad, and the PID resumes in auto at the last SP with the baseline gains stored in the PLC (L2-5).
- Permissions reuse Forge's model: a service identity per controller with
ot:tag:writeon its own tags, neverot:interlock:bypass(L2-13).Speaker notes
- Record §2.2, §2.3 and §2.5; the autonomy model is one mechanism for both layers (L3-5), built and audited once.
Process Control · Where It Stands
| Item | State |
|---|---|
| Decision record signed by the owner (rounds 1 to 3, Q-1 to Q-50) | ✅ 2026-11-13 (D-11, the owner's PR 93) |
| Forge review of the tree for O-2 to O-4 (write path, scopes, loop model, schemas, FVTS, one clock) | ✅ 2026-11-13, record §4a; FB-112 recorded |
| Framework Functional Specification Document (FSD), then PC-L1, PC-L2 and PC-L3 FSDs; an FxTS spec per contract before code | ⬜ FB-110, after the owner's round-4 answers (nine questions: the FSDs' home and format, the module's language O-2, the mapping O-3, a CONTROLLER write origin, the PLC contract's home, batch phase as a context field, a one-clock refusal as a shed event, publication before the prior-art search, a provenance line) |
| The MPC Supervisor module (all of PC-L2; a new build to the SDK) | ⬜ language decided after the review (O-2) |
Controller write path: a CONTROLLER origin, a cycle write, a heartbeat class, write timing on the status |
⬜ FB-112, designed in the PC-L2 FSD |
| PC-L3 agent topology | [OPEN] O-1; the FSD notes it undecided |
| Prior-art search on the framework's novelty | ⬜ FB-111, before any IP filing or public positioning |
- What the tree gives it today: the OT write engine's defense chain (one tag per write, pre-read, write, read-back, audit), OPC UA to Logix, the decision models for proposals and approvals, and the one-clock rules every spoke follows: an MPC deployment is a spoke, so its FACTS
time_governancedeclaration applies and a refused connection sheds its loops. - Nothing of the framework is implemented, and nothing is before its FSD (WS-12, roadmap sequence item 12).
Speaker notes
docs/ROADMAP.mdWS-12 and D-11;docs/WHERE-WE-ARE.md§3.13. The record's §4a holds the review's facts and its [PROPOSED] answers; the owner's signature does not cover those.
F5 · Honest State
| Gap | Backlog / decision |
|---|---|
| Source time is corrected to master on OPC UA only; the Logix, S7 and Modbus readers follow their drivers; the FACTS declaration is in place | FB-094 and FB-090 done 2026-11-13; FB-093 enforces |
One adapter identity (code forge-ot-module, manifest and spec ot-module) |
FB-079 (includes FB-018) |
| Batch context resolver wired to MES | FB-020 |
| OT FACTS vocabulary | D-8 |
| OT reference FVTS spec with real tags, owner-approved | FB-078 |
| The three-layer process control framework: decided (D-11), not built; FSDs after the owner's round-4 answers | FB-110, FB-111, FB-112 |
Next: how modules are built and shown.
F6 · Modules, the Module Builder and forge-display
Nav: ← F5 · ⇤ TOC · ⇅ Landing fork · F7 →
How new capability enters Forge: the language policy, the module builder's pattern, what exists in Go, the interim MES bridge and its Go rewrite, and the one UI runtime.
Speaker notes
- Source:
docs/ROADMAP.md§1 (A-2, A-3, A-5),docs/MODULE_BUILDER.md,docs/WHERE-WE-ARE.md§3.6–§3.8,docs/FxTS/FVTS.md.
The Language Policy
| Component | Language | Status |
|---|---|---|
| Hub (forge-core) | Python ≥ 3.12, FastAPI, Typer, Pydantic v2, uv, ruff | in force |
Management and integration modules (forge-<service>) |
Go, generated from the module SDK (A-2, A-5) | in force; the Go forge-mes is FB-076 |
| Spokes | Python inside the hub, or any language that speaks the proto as an external process | in force |
| forge-mes today | the migrated NestJS/Next.js application runs as the interim MES bridge until the Go module replaces it | bridge in place; the Go design signed (D-3, 2026-11-03) |
| User interfaces | none in modules: forge-display renders every surface from FVTS specs (A-3) | runner and reference renderer exist; the renderer does not |
Speaker notes
The Module Builder Six-File Pattern
docs/MODULE_BUILDER.mdis the from-first-principles guide (~20 minutes, no prior Forge knowledge assumed): manifest, config, adapter class, context mapper, record builder, the FACTS spec, testing, CLI and API reference, common patterns, troubleshooting.src/forge/sdk/module_builder: manifest builder, scaffolder, generators and its CLI.- The reference spoke is
src/forge/adapters/whk_cmms(adapter, config, context, record builder, topics, entity mappers).Speaker notes
- Honest: the templates are adapter-style and backend-only (FB-017), and duplicate SDK copies drift (FB-019). The Go module template does not exist yet (M3).
Go Today
| Piece | State |
|---|---|
go/internal/models |
✅ the core models mirrored, 1,800 lines with 1,488 of tests; Lot.item_id (FB-010) and the RecordContext slots (FB-013); every manufacturing entity has a New* constructor with the Python defaults and a Validate(), held equal to the Python models by one fixture both suites read (FB-016) |
go/gen/forge |
✅ generated bindings from the one proto set (Buf) |
go/internal/scaffold |
🟡 112 lines; not a module template yet |
forged daemon, forgectl |
⬜ placeholders |
| CI | go build, gofmt -l, go vet, go test in the hub-go job |
The route (M3): the module SDK template in Go; forge-mes phase 1 registers, ingests and takes write-backs against the hub with the transport parity tests (FB-055) as the acceptance test; mod_mes in the hub (FB-057); changeover and MQTT in Go; parity; cut-over; the NestJS backend retired.
Speaker notes
- The Go models become the MES module's types, so the data-model items (FB-010, FB-011, FB-012, FB-016) were settled first.
forge-mes · The Interim Bridge and the Go Rewrite
| Capability | State |
|---|---|
NestJS backend + Next.js frontend imported as the bridge (modules/Forge MES); the spoke speaks the contract (push, pull, Collect, token, TLS) |
✅ |
FACTS spec forge-mes (18 data sources incl. the AuditLog backfill), approved |
✅ |
| Go rewrite from the module SDK | ⬜ FB-076: decided (A-2) and designed (D-3, signed 2026-11-03); the Go SDK scaffold (FB-017) is the first step |
Prisma data into the hub's mod_mes |
⬜ FB-057 steps 2–5 |
| Frontend retired in favour of forge-display | ⬜ after forge-display exists |
- The bridge's jest and tsc gates are advisory in CI (FB-048) and go away when FB-076 retires that code.
- The bridge was imported from
WhiskeyHouse/whk-meson 2026-10-15; the import's credential leak is why the repository's history was purged and the hardening of F8 exists.Speaker notes
- Wording rule again: "the interim MES bridge", never "TypeScript forge-mes".
forge-display · Modules Describe, the Renderer Renders (A-3)
- A module publishes points (units, precision, ranges, staleness), alarms, actions, surfaces and the render profiles it supports; a module can only tighten the baseline, never loosen it.
- forge-display enforces nothing safety-critical itself (the core does); it ships staleness marking, bad-quality handling, ISA-101 presentation, alarm annunciation and action feedback with audit confirmation.
- Today: FVTS v0.1.0 schema, the 19-check runner, the render-profile baseline, a reference renderer, golden messages and a CI gate (FB-077). The renderer itself has no code; its open items were decided on 2026-11-03 (D-4), so its design is next (M4).
F6 · Honest State
| Gap | Backlog / decision |
|---|---|
| Go module SDK template; forge-mes in Go | FB-017, FB-076 (D-3) |
| Module builder templates adapter-style; duplicate SDK copies | FB-017, FB-019 |
| forge-display runtime | D-4 decided 2026-11-03; design next, no code yet |
Template module copies (modules/Forge CMMS, Forge ERPI, Forge DB Orchestration) are adapter templates, not Go modules |
docs/WHERE-WE-ARE.md §3.7 |
| The MPC Supervisor module (all of PC-L2) is a new build to the SDK; its language is open (O-2, with D-7) | FB-110 (D-11) |
Next: how a value becomes decision-quality.
F7 · Context, Curation and Decisions
Nav: ← F6 · ⇤ TOC · ⇅ Landing fork · F8 →
From a raw value to a decision-quality figure and a recorded decision: the Context Engine, the manufacturing entities, the curation pipeline, data products with lineage, and the decision frame.
Speaker notes
- Source:
docs/VISION.mdP-2, P-3, P-9;docs/PRINCIPLES.md§4;docs/WHERE-WE-ARE.md§3.2–§3.3;src/forge/context,src/forge/curation,src/forge/core/models.
Context Is a First-Class Citizen
- A spoke's FACTS spec maps source fields to Forge context fields and declares enrichment rules; the hub fills what the source cannot: shift from timestamp, area from location, lot from the active batch.
- The Context Engine (F21) is served by the hub under
/v1/context(12 routes; state changes behindcontext:write) with Postgres stores through the factory (FB-001, FB-005). - The context field registry (
src/forge/core/registry) is the vocabulary;RecordContextcarries it slot for slot (FB-013). - The manufacturing entity catalog (
docs/core/manufacturing-entity-catalog.md) and the ISA-95 / ISA-88 hierarchy inforge.core.models.manufacturingdefine what context means:MaterialItem,Lot(withitem_id, FB-010),ProductionOrder, equipment and areas. - Context is never silently dropped (invariant).
| Open | Backlog |
|---|---|
| Step and phase execution, electronic batch record entities | FB-011 |
| Typed ISA-88 hierarchy | FB-012 |
| Equipment registry served from Postgres | ✅ migration 009 |
Speaker notes
- "Solved when": no record is persisted without its required context fields, and the required set is declared per spoke and checked by the FACTS gate.
Curation · From Raw Records to Data Products
- One curation engine builds each data product's pipeline from its
CurationSpec(migration 010) and runs it on ingest for the published products the adapter feeds; curated records are persisted with the raw ones (FB-009). forge.curation:pipeline.py(multi-stage normalization and enrichment),normalization.py(field normalization, unit conversion),aggregation.py(time windows),quality.py(scoring and validation),lineage.py(provenance).- The curation service is mounted at
/curation; data products live inforge_canonical.data_products.
Data Products
| Property | Meaning |
|---|---|
| Versioned | a product's definition changes by version; consumers pin one |
| Quality objectives | what "good" means for this product, visible beside every figure derived from it |
| Lineage | the chain from raw record through each transformation to the product, recorded and queryable |
| Curation spec | the pipeline the engine builds and runs for the product |
| Owner, status | who answers for it; draft, published, deprecated |
- "Solved when": every figure on a surface can be traced to its sources and transformations, and its quality objective is visible beside it (P-3).
- The same curated products are the training and evaluation sets for site-specific models, so expertise is captured where it is exercised.
Speaker notes
DataProductis a Pydantic model inforge.core.models.data_product; migration 003 mirrors it and the test suite holds the key fields.
Decisions Are Records
The research basis (docs/PRINCIPLES.md §4): decision quality degrades from incomplete information and from undisciplined judgment. Collection, governance, storage, curation and serving address the first; the decision-support layer addresses the second.
| Requirement | Why |
|---|---|
| Preserve and surface base rates beside alerts | base-rate neglect |
| Normalise and segment before comparing; declare the basis or say "unnormalised" | Simpson's paradox |
| Link multi-departmental context; show several departmental views of the same data | spurious correlation, framing |
| Require disconfirming evidence before action hardens; distinguish confidence from evidence | structured challenge, procedural not optional |
For significant decisions the 13-point minimum frame is recorded: scope, current hypothesis, supporting evidence, challenging evidence (required), alternative hypotheses, key assumptions with confidence, missing information, risk if wrong, opportunity if right, existing controls, evidence of effectiveness (required), reassessment trigger, a named owner.
forge.core.models.decisionholds the decision with the products and lineage it relied on; outcomes are observed against it (forge.observer).- Every assumption is a tracked entity (active / validated / invalidated / superseded); new data that contradicts an active assumption alerts its owner.
Speaker notes
- "Solved when": a decision can be replayed: what was known, what was decided, what happened (P-9).
F7 · Honest State
| Gap | Backlog / decision |
|---|---|
| FQTS, FNTS, FLTS as gates | stubs or planned (M5) |
| Step/phase execution, electronic batch records; typed ISA-88 hierarchy | FB-011, FB-012 |
| Decision-support module with the 13-point frame as a workflow | the models exist; the module does not |
| Routing registry convergence (which store a schema lives in) | FB-097 (D-10) |
Next: who may do what, and how sites keep working offline.
F8 · Security, Identity and Federation
Nav: ← F7 · ⇤ TOC · ⇅ Landing fork · F9 →
The gateway as it is, the role model as it is designed, the hub of hubs, Forge-issued credentials, and the repository's own security posture.
Speaker notes
- Source:
docs/VISION.mdP-10, P-11, §3.6;docs/decisions/roles.md;docs/WHERE-WE-ARE.md§3.10;docs/ROADMAP.md§1 (A-9).
The Gateway Today
| Capability | State |
|---|---|
Auth, RBAC and rate-limiting middleware (forge.gateway) |
🟡 exists; auth off by default |
Scopes on state-changing routes: adapters:write, context:write, schemas:write |
✅ |
| Reads are open | 🟡 FB-007 |
| Scoped roles enforced on every route and RPC | ⬜ FB-075 (two role enums today: gateway Role, OT WriteRole) |
OT control POST endpoints behind adapters:write |
✅ FB-082 |
- "Solved when": the gateway enforces scoped roles on every route and RPC, modules hold only Forge-issued credentials, and a visibility rule such as "ERP hidden from distillery operators" is a configuration, not code (P-11).
Speaker notes
- Do not mistake the development default for the design: auth is off so the stack runs on a laptop; the role model below is what the gateway will enforce.
The Role Model · R-1 … R-19 (D-1 signed 2026-11-03)
Designed in dialogue in docs/decisions/roles.md; enterprise-class:
- Identity is established by the installation's chosen method (OIDC, local accounts and service identities first; then Lightweight Directory Access Protocol (LDAP)/AD; then Security Assertion Markup Language (SAML), R-10), but Forge decides what an identity may do (R-2).
- Roles are scoped (R-7), shipped per module as data (R-12), chosen in shape by the installing administrator (R-3, R-4), and constrain reads as well as actions (R-11).
- Roles are assigned at the managing hub and inherited downward (R-16); tokens verify offline against the issuing hub's public key with a one-hour default lifetime (R-8, R-15).
- Separation of duties (two-step review, interlock bypass with reason, approvals) is evaluated by the hub (R-6).
- Resolved 2026-11-03: Q21, a derived copy of assignments at the site hub, refreshed from the managing hub and never edited locally (R-18); Q22, the four-role ladder as an optional preset, off by default (R-19). FB-075, FB-078 and the multi-party approval step above FB-074 can start.
Speaker notes
- The record's format is the one every design record follows: status line for the owner's signature, participants, tagged statements, numbered proposals and questions.
Hub of Hubs (P-10, R-9)
- Every hub owns what is attached to it directly (spokes, child hubs, subjects) and collects, governs, stores, curates and serves that data (R-13, R-14).
- Nothing communicates through a hub; a transfer occurs at it.
- Audit records always flow upward; other data is requested on demand unless a site opts into replication (R-17).
- A site keeps working when the WAN does not: full operation for the token lifetime, audit complete on reconnection.
- The time-authority chain follows the hub hierarchy (one clock, F5).
- State: no code; milestone M6.
Speaker notes
- "Solved when": a site hub runs for the full token lifetime with the enterprise unreachable, and the enterprise's audit view is complete when the link returns.
Credentials and Secrets
- The hub owns the databases and issues credentials (
forge db access, F3): a module never carries a database password it created itself; the password is printed once and never stored. - Hub ↔ spoke traffic is TLS or mTLS in both directions with a per-spoke callback token.
- Configuration comes from
.envfiles and environment variables; no credential, IP or key is hard-coded. - gitleaks runs on every pushed commit in CI (
secrets-scan) and before every push locally; nothing is imported into the repository without a history scan and a purge plan.Speaker notes
- The compose stack's
changemedefaults are development placeholders for the infrastructure containers, overridden by the environment; they are not Forge-issued credentials.
- The compose stack's
The Repository Security Posture (A-9)
| Measure | State |
|---|---|
| Repository public again since 2026-10-17 (owner's decision) | ✅ |
Secret scanning, push protection, CodeQL default setup, Dependabot (Python on the uv ecosystem), private vulnerability reporting, fork-PR approval |
✅ |
| gitleaks in CI on the pushed commits | ✅ |
| The 2026-10-15 import leak: credentials rotated, history purged, the purged refs with GitHub Support until GC | 🟡 ticket open |
| Non-provider patterns and validity checks (owner toggles the API refuses) | FB-044 |
- Lesson that binds: every import is scanned before it lands, and secrets never enter a commit; the PR workflow and the backlog rule exist in part because of this incident.
Speaker notes
docs/WHERE-WE-ARE.md§3.10 carries the current state of the alerts and the support ticket.
F8 · Honest State
| Gap | Backlog / decision |
|---|---|
| Scoped roles enforced in the gateway; reads open | FB-075, FB-007 (D-1) |
| Identity methods | R-10, not started |
| Hub of hubs, offline tokens | M6, no code |
| Security test specification (FSTS) | stub |
Next: landing a change.
F9 · Contributing
Nav: ← F8 · ⇤ TOC · ⇅ Landing fork · F10 →
Setting up, the workflow, the rules that bind, where each kind of change goes, how to add a spoke, and the governed memory that watches over the agents working here.
Speaker notes
- Source:
README.md"Development",docs/ROADMAP.md§1 (A-8, A-10),docs/PRINCIPLES.md§9,.github/workflows/ci.yml,BACKLOG.mdheader.
Set Up
git clone https://github.com/reh3376/forge.git && cd forge
uv sync --locked --extra dev --extra ot # the same command CI and the hub image run
uv run pytest tests -q # 4,584 tests, ~1 minute
uv run ruff check . && uv run ruff format --check . # both block CI; ruff is pinned exactly
(cd go && go build ./... && go vet ./... && go test ./...)
docker compose -f deploy/docker/docker-compose.yml up -d # postgres, timescaledb, neo4j, redis, kafka, rabbitmq, minio
- Python 3.12+, uv, ruff, Docker for the services; Go 1.26 for
go/; Node 20 for the interim MES bridge's CI job and Node 22 for the tutorial build. - Every Python dependency is locked in
uv.lock;--lockedfails on a stale lock, so a dependency moves only through a committed re-lock (FB-096):
uv lock --upgrade-package fastapi # one package, within its pyproject range
uv lock --upgrade # everything the ranges allow; then commit uv.lock
Speaker notes
tests/test_dependency_lock.pyholds the lock to the manifest and every installer (CI, the Dockerfile, the README quick start) to the lock.- The hub image builds from the lock with the dependency layer before the source and the dev tooling out (
deploy/docker/Dockerfile.forge).
The Workflow (A-8)
- One backlog item per PR. Never push the next item onto a branch with an open PR: commit locally, push after the merge.
- The PR is opened by the workflow with the bot as author, so the owner can approve it; nobody opens PRs as the owner.
- Docs-only commits may ride along with an item; everything else is its own PR.
- Conventional Commits (
feat:,fix:,docs:,build:).Speaker notes
- CI runs on every push to every branch so checks attach to the commits behind auto-opened PRs; same-repo PRs do not run twice.
The Rules That Bind
| Rule | Since |
|---|---|
Every finding is fixed or recorded in BACKLOG.md; nothing is skipped |
2026-10-15 |
Documentation is current before every push: docs/WHERE-WE-ARE.md rows, numbers and status date, README.md counts, the roadmap and backlog |
2026-10-16 |
Only the owner approves a spec hash (forge governance approve --by reh3376) and signs a design record, on their explicit word |
A-9, FHTS |
| Forge-issued passwords are printed once and never stored | FB-057 |
Local models only for the project's tooling (MDEMG/Jiminy on mdemg-llm-v1); never a cloud model |
A-10 |
| Nothing imported without a gitleaks history scan; gitleaks before every push | A-9 |
Never git push --force, never rm -rf, never a bare DROP of a table, schema, index or database, never the SQL verb that empties a table in a command (the hook matches the bare word in any case, inside identifiers too: reword, never work around); the governance hook denies them |
Jiminy PreToolUse |
| A migration already applied is never edited; a repair is a new revision | F3 |
| Wording: the NestJS/Next.js code is "the interim MES bridge"; forge-mes is Go | owner |
Speaker notes
- The hook is deterministic enforcement at the point of action: when a command is blocked, comply, reword minimally, surface it, never engineer a workaround.
Where Each Kind of Change Goes
| You want to… | Do this |
|---|---|
| fix something you found while doing something else | finish the item; add a BACKLOG.md row (ID, severity, problem, where, suggested fix) if you did not fix it |
| add or change a hub route | add or update the FATS spec; the hub test holds both directions |
| add a spoke | scaffold with the module builder; write the FACTS spec; run forge governance run facts <spoke>; the spoke registers only when the manifest matches the approved spec |
| change a stored shape | a new migration (never edit an applied one); a test in tests/storage/test_migrations.py that reads the migration source |
| expose a surface from a module | an FVTS spec; the runner checks it against the render-profile baseline |
| propose a design the owner must decide | a record in docs/decisions/ (status line, [OWNER]/[FACT]/[PROPOSED]/[OPEN], P-n proposals, Q-n questions); list it as D-n in ROADMAP.md §5 and the gates table; wait for the signature before implementing |
| change a governed spec | edit, forge governance stamp, leave it pending_review; the owner approves |
| bump a dependency | uv lock --upgrade-package <name>, commit uv.lock with the change |
Speaker notes
Adding a Spoke in a Day (P-5)
- Scaffold: the module builder generates manifest, config, adapter, context mapper, record builder and a FACTS spec skeleton (
docs/MODULE_BUILDER.md§3–§4). - Declare: fill the FACTS spec: identity and tier, capabilities, connection, data sources with schema references, context mapping and enrichment, error handling, sample records.
- Validate:
forge governance validate-specthenforge governance run facts <spoke>; fix every violation; stamp. - Implement:
collect,ingest, lifecycle and health inadapter.py; mappers turn source rows intoContextualRecords with the context the spec declares. - Test: spec tests, runner tests and adapter tests under
tests/; the suite stays green. - Register: the hub checks the manifest against the spec at Register; with the owner's approval of the hash the spoke is live.
"Solved when": onboarding a new system is a day's work from the SDK, and a conformance failure anywhere blocks the merge, not the plant.
Speaker notes
- The spoke onboarding priority and checklist are in
docs/PRINCIPLES.md§8; compliance plans for two external spokes are indocs/spoke-onboarding/.
Testing Conventions
tests/mirrorssrc/: 267 files, 4,584 collected; the full suite runs in about a minute on the locked dependency set.- Migration tests read the migration source and hold it to the models and writers; they do not need a database. Behavioural verification of a migration runs on a throwaway container and is recorded in the backlog row.
- Governance tests assert schema–runner parity and run every spec through its runner; FVTS has golden messages.
- The Go suite holds the Go models equal to the Python models through one shared fixture.
- Counts in
README.mdanddocs/WHERE-WE-ARE.mdare updated with every push that changes them (pytest --collect-only -qfor the collected count).Speaker notes
-p no:cacheproviderkeeps the repository clean of.pytest_cache; the CI job runs the same flags.
MDEMG and Jiminy · Governed Memory for the Agents
- The repository runs its own MDEMG instance (a local, graph-backed project memory) with Jiminy as the governance layer; constraints, corrections and outcomes live in the graph, not in markdown.
- The J17 handshake: identify by session, request the constraints for the task at hand, acknowledge them, act under enforcement, report the outcome.
- The PreToolUse hook enforces constraints deterministically at each tool call, whether or not the agent has read anything; a blocked action is the protocol working.
- Models: the local llama-server model
mdemg-llm-v1; no cloud model, ever (A-10). - This is problem P-7 applied to the engineering platform itself: the more AI assistance, the more the contracts and the workflow must be machine-enforced.
Speaker notes
- The vision counts the engineering platform as part of the product (
docs/VISION.md§3.7): one item per PR, owner merges on green, findings fixed or recorded, docs current, owner-only approvals, local models, governed memory.
- The vision counts the engineering platform as part of the product (
F9 · Recap
uv sync --locked, pytest, ruff, go test; the compose stack for services.- One item, docs current, gitleaks, push, auto-PR, CI green, the owner merges, fast-forward sync.
- Findings fixed or recorded; only the owner approves and signs; passwords never stored; local models only; the hook's denials are final.
- Routes get FATS specs, spokes get FACTS specs, surfaces get FVTS specs, stored shapes get migrations, owner decisions get design records.
Next: where we are and where to go.
F10 · Conclusion
Nav: ← F9 · ⇤ TOC · ⇅ Landing fork
The honest state against the vision, the milestones, the decision queue, what is next, and where to go from here.
Speaker notes
- Source:
docs/WHERE-WE-ARE.md§4–§5,docs/WHERE-WE-ARE-GOING.md§3–§5,docs/ROADMAP.md§4–§5.
The Largest Gaps Against the Vision
- No forge-display: the contract and runner exist; the renderer does not.
- No management module in Go: the interim MES bridge stands in for forge-mes; the SDK template does not exist yet.
- No scoped roles in force: the gateway's auth is off by default; the role model is signed (D-1, 2026-11-03) and not yet enforced (FB-075).
- No federation: a single hub only; no hub-of-hubs code.
- Seven governance frameworks are stubs or planned; FACTS validates against its own schema and all nine of its specs carry owner-approved hashes (2026-11-13).
- No production deployment: compose only.
- Clock discipline declared, not yet enforced: every spoke declares how it is time-governed (FB-090) and the deployment requirement is written down, but the hub is not yet a time authority for what is attached to it and nothing refuses a wrong clock (FB-093; hub time in the contract, FB-092).
- Process control decided, not built: the three-layer framework is signed (D-11, 2026-11-13) and waits for its FSDs.
Speaker notes
docs/WHERE-WE-ARE.md§5 verbatim in substance. Each gap has backlog ids and a decision it waits on.
Milestones
| Milestone | Outcome | State |
|---|---|---|
| M1 · Contract and governance floor | hub ↔ spoke end to end; OT module in the hub; FATS, FACTS, FTTS, FVTS with runners and gates; FHTS hashing | Done (PRs through 36) |
| M2 · Decisions and designs | role model (D-1), forge-mes Go design (D-3), FVTS open items (D-4), OT FACTS vocabulary (D-8), one clock (D-9), one schema registry (D-10), process control (D-11); OT reference FVTS spec approved | Mostly done: six decisions signed 2026-11-03, D-11 on 2026-11-13; the OT FVTS spec (FB-078) open |
| M3 · Go SDK and the first Go module | Go module template; forge-mes phase 1 against the hub; mod_mes; changeover and MQTT in Go; cut-over |
not started |
| M4 · forge-display | renderer scaffold and spike; MES surfaces first, then OT HMI | unblocked 2026-11-03 (D-4 decided) |
| M5 · Hub platform hardening | Context Engine and Schema Registry (done), scoped roles, persistent access control (done), FDTS/FQTS/FSTS from stub to gate | started |
| M6 · Enterprise | hub of hubs, identity methods, offline tokens, Kubernetes, backups and SLOs; forge-cmms and forge-whs in Go; forge-ignition | not started |
Speaker notes
- Milestones overlap where the sequence allows: forge-display can start now that D-4 is answered, in parallel with M3.
The Decision Queue (owner input)
| # | Decision | State |
|---|---|---|
| D-1 | Platform role model (Q21, Q22) | signed 2026-11-03; FB-075, FB-078 and the multi-party approval above FB-074 can start |
| D-3 | forge-mes Go design (docs/decisions/forge-mes-go.md) |
signed 2026-11-03; ten steps, the Go SDK scaffold first |
| D-4 | FVTS open items (name, write authority per profile, mobile acknowledge, transport, layout) | decided 2026-11-03; forge-display design next |
| D-7 | Scope of the Go standard (OT module, Python adapters) | open |
| D-8 | FACTS vocabulary for OT adapters | decided 2026-11-03: extend the enums; FB-079 can start |
| D-9 | One clock: which established standards to adopt (docs/decisions/one-clock-ot-source-time.md) |
signed 2026-11-03; FB-088, FB-094 (steps 2, 3, 6) and FB-090 done 2026-11-13; FB-093, FB-092, FB-091 follow in the record's step order |
| D-10 | One schema registry (docs/decisions/one-schema-registry.md) |
signed 2026-11-03; FB-097's eight steps |
| D-11 | Three-layer process control framework, PC-L1/PC-L2/PC-L3 (docs/decisions/process-control-framework.md) |
signed 2026-11-13 by the owner; Forge review done; the FSDs follow the owner's round-4 answers (FB-110) |
On 2026-11-03 the owner answered the open questions one at a time (34 answers) and declared the answers the signature; every gated item can start. Two standing rules came with the answers: no silent failure, and no decision that pins the platform in.
Speaker notes
- A design record is signed by the owner editing its status line; implementation does not start before that.
What Is Next
A decision session on D-1, D-3, D-4, D-8, D-9 and D-10(done 2026-11-03, one question at a time) andthe FB-076 design document(signed the same day); D-11 signed 2026-11-13.- The one-clock steps in the record's order: FB-088, FB-094 and FB-090 done 2026-11-13; FB-093 (fail-closed enforcement at Register and Ingest) next, then FB-092 (hub time in the contract) and FB-091 (the time-quality dimension); the one-registry steps (FB-097, D-10) before the Go module's first ingest.
- The module SDK Go scaffold (FB-017); its first consumer is the Go forge-mes.
- FB-076 phase 1: the Go module registers, ingests and takes write-backs against the hub.
- FB-057
mod_mes, with FB-004 and FB-059 as the Go module needs them. - FB-076 phases 2–3: changeover and MQTT, parity, cut-over.
- forge-display scaffold and renderer spike; MES surfaces first.
- Hub platform items (FB-007, FB-075) as the Go module and forge-display start needing them.
- Process control (D-11, WS-12): the framework FSD, then the PC-L1, PC-L2 and PC-L3 FSDs, each contract an FxTS spec before code; after the owner's round-4 answers, beside items 3 to 6.
Speaker notes
docs/WHERE-WE-ARE-GOING.md§4; the detailed sequence with dependencies isdocs/ROADMAP.md§4.
Where to Go Next
| If you want to… | Open |
|---|---|
| see the destination in full | docs/VISION.md |
| see what gates the route | docs/WHERE-WE-ARE-GOING.md §5 |
| see what exists today, component by component | docs/WHERE-WE-ARE.md §3 |
| pick up an item | BACKLOG.md and docs/ROADMAP.md §6 (open backlog by workstream) |
| write a spoke | docs/MODULE_BUILDER.md, docs/governance/facts-developer-guide.md |
| understand a framework | docs/FxTS/<FRAMEWORK>.md |
| read a decision in progress | docs/decisions/ |
| understand why things are the way they are | docs/PRINCIPLES.md |
Thank you. Return to the landing fork ↑ · Continue to the End User path ↓
Speaker notes
- Natural final Q&A anchor. The end-user path follows for anyone who wants the operator's view of the same system.
U1 · Start Here · The End User Overview
Nav: ⇤ TOC · ⇅ Landing fork · U2 →
This track is for the people who will run a Forge site or decide from it: operators, supervisors, planners, maintenance and quality staff, and the managers above them. No code. Plain language. It is complete on its own.
| Section | What you get |
|---|---|
| U1 Start Here | what Forge is for, the problems it solves for you, what it is not |
| U2 How Data Flows | from a plant system to a screen, in six steps |
| U3 The Hub You Run | what is running, how to tell it is healthy, the command line |
| U4 Your Systems as Spokes | the connected systems and what their contracts mean to you |
| U5 The Plant Floor | tags, alarms, writes, changeover, the three layers of control above the PLC |
| U6 Context, Products, Decisions | why "area" means one thing, where figures come from, recording a decision |
| U7 Governance for Users | what "approved" means and why nothing changes silently |
| U8 Screens | what you will look at, and what you look at today |
| U9 Identity, Roles, Credentials | who may do what |
| U10 Operations | how a site is run, backed up and upgraded |
| U11 Where to Go Next | documents, asking for a change, returning to the fork |
Speaker notes
- The dev path (F1–F10) covers the same system for engineers. Nothing here depends on it.
What Forge Is, in One Paragraph
Forge sits between the systems a plant already runs on and the people who need to decide from their data. Every system (the control system on the floor, the manufacturing execution system, the warehouse, maintenance, the ERP, the historian, scanners) connects to one hub as a spoke. Every value that crosses into the hub is checked, stamped with the hub's clock, and tagged with the context it belongs to: which site, area and equipment, which lot and work order, which shift and operator, which operating mode. From those records the hub builds data products whose figures carry their sources and a stated quality, renders the screens people use from declared contracts, and records the decisions taken on them. Forge's own modules for MES, warehouse, maintenance and the plant floor are optional: a site can keep its existing software and use Forge as the layer that connects and governs it, or replace that software one module at a time.
Speaker notes
docs/VISION.md§1 in plain words. "Hub" is the Forge server for a site; "spoke" is any connected system.
The Problems It Solves for You
| What you live with today | What Forge does about it |
|---|---|
| A dozen systems, each with its own identifiers, units and clocks; four screens open to answer one question | every system speaks one contract to the hub; every record is one shape with context attached, so the answer is one query |
| A number on a dashboard that nobody can trace or trust | every figure carries where it came from, what was done to it and the quality it is held to |
| Setpoints written from a screen with no role check, no confirmation, no record | every write passes a defense chain in the core: validation, review, interlocks, authorization, read-back, audit |
| Each application with its own screens, its own alarm banner, its own mobile story | one rendering layer draws every screen from a declared contract, on desktop HMI, desktop, web and mobile |
| Passwords in config files; "admin or not" | the hub issues credentials and roles are scoped to what a person does, where |
| A site that stops when the link to headquarters drops | each site hub keeps working on its own; audit flows up when the link returns |
| A contract between two systems changed quietly in a commit nobody read | every contract is hashed; only the owner approves a change; an unapproved change fails before it ships |
Speaker notes
docs/VISION.md§2 (P-1 to P-12) in the end-user's terms.
What Forge Is Not
- Not a PLC programming environment. It reads and writes PLCs through OPC-UA; ladder logic and function blocks stay in the vendor tools.
- Not an ERP, accounting or HR system. It integrates them as spokes and may host a management module beside them; it does not replace the ledger.
- Not a cloud service. It is enterprise software installed per site and per enterprise, with local models for its own tooling.
- Not a general dashboarding product. forge-display renders Forge modules; it is not a UI framework for third parties.
Speaker notes
docs/VISION.md§5.
U2 · How Data Flows
Nav: ← U1 · ⇤ TOC · ⇅ Landing fork · U3 →
- A spoke reads from or subscribes to a plant system and sends records to the hub; the hub can also ask the spoke for data on demand, backfill history, or write back into the system.
- The hub checks the spoke against its contract before it is allowed in, and checks every record.
- The hub stamps when the record arrived with its own clock and measures how far the spoke's clock is from its own.
- The record gets its context; what the source could not say (the shift from the time, the area from the location, the lot from the active batch), the hub fills in.
- Records are stored in the store that fits them; the hub owns every database.
- Data products are built from the records and feed screens, decisions and, where a site chooses, training data for its own models.
Speaker notes
- Honest: today the hub measures clock offsets and warns, and every connected system declares how it keeps time in its contract (2026-11-13); refusing a spoke whose clock is out of tolerance is decided (D-9, signed 2026-11-03) and not yet enforced (FB-093).
One Record Type
Every value that enters the hub is a contextual record:
| Part | Holds |
|---|---|
| the value | the number, text or state, its data type and units |
| the quality | good, bad or uncertain, carried with the value, never hidden |
| the times | when it happened at the source, when the spoke sent it, when the hub received it; always UTC with its zone |
| the source | which spoke, which system, which tag or table, which version of the contract |
| the context | site, area, equipment, operating mode, lot, batch, recipe, work order, shift, operator, event |
Because every record has the same shape, "fermentation temperature of Cooker 01 during lot L-2026-0412 on the night shift" is a question the hub can answer without anyone mapping systems by hand.
Speaker notes
- Two values can be joined only if the words mean the same thing everywhere; U6 explains how "area" is kept the same.
One Clock
Forge exists so that people at every level decide from the same picture, and records from different sources only line up if their timestamps come from the same master time.
- The highest hub is the time authority; every hub governs the clocks of the modules and spokes attached to it; every spoke governs or measures the clocks of the systems behind it.
- Every stored timestamp is UTC with its zone; the hub stamps receipt with its own clock; the offset of every connected clock is measured and shown.
- A hub, module or spoke outside tolerance is refused: warnings are not a substitute for correction.
- For a plant-floor tag, the time that counts is when the value occurred at the device, corrected to master time, never the poll time passed off as device time.
Where it stands: timestamps are UTC and receipt is stamped; offsets are measured and warned on; on the plant floor a tag's time is corrected to the master clock by the server's measured offset (OPC UA, since 2026-11-13), no time is ever invented, and every connected system declares how it keeps time in its contract. Refusing a bad clock is decided (D-9, signed 2026-11-03) and is the next step (FB-093).
Speaker notes
- The owner's principle of 2026-10-18;
docs/PRINCIPLES.md§2.
U3 · The Hub You Run
Nav: ← U2 · ⇤ TOC · ⇅ Landing fork · U4 →
What is running on a site hub, how to tell it is healthy, and the command line.
What Is Running
| Component | Purpose |
|---|---|
| forge-hub | the hub itself: the REST API, the gRPC endpoint spokes connect to, the OT module, governance, the CLI |
| PostgreSQL | the hub's own tables, the data product catalogue, one schema per module |
| TimescaleDB | time series: every contextual record |
| Neo4j | lineage and topology |
| Redis | cache and sessions |
| RabbitMQ and the embedded MQTT broker | module events and plant-floor messaging |
| MinIO, Kafka | object store; the enterprise bus for later |
Today this runs from Docker Compose for development; production is a Kubernetes deployment per hub, which is not built yet (U10).
Speaker notes
deploy/docker/docker-compose.yml; the hub image is built from the locked dependency set.
Is It Healthy?
forge health # the platform's own view
curl http://<hub>/v1/health # every component: postgres, timescaledb, neo4j, redis, kafka, rabbitmq, minio
curl http://<hub>/readyz # ready to serve?
forge adapter list # which spokes are registered
forge adapter status <spoke> # one spoke's state, including its clock offset
- A spoke's health report includes how far its clock is from the hub's; the hub's ingest statistics show offsets per link.
- The observer (health, liveness, service-level objectives, backup status) exists as a package; its objectives and alerts are a planned framework (FOTS).
Speaker notes
GET /v1/ingest/statsand OpenTelemetry metricsforge.clock.offsetandforge.clock.out_of_tolerancecarry the clock picture.
The Command Line
| Command | Does |
|---|---|
forge version, forge health, forge init |
version, health, a new instance |
forge adapter list, forge adapter status <id> |
registered spokes and their state |
forge governance specs [--pending] |
every contract's approval state; what awaits the owner |
forge governance run <framework> <spec> |
run one contract's checks |
forge migrate up, status, down |
apply, show or roll back database migrations |
forge db access grant / revoke / list / issue |
give a module access to a schema and hand it a credential, printed once |
Speaker notes
- Approving a contract (
forge governance approve) is the owner's command alone (U7).
U4 · Your Systems as Spokes
Nav: ← U3 · ⇤ TOC · ⇅ Landing fork · U5 →
Which systems connect, and what the contract behind each one means to the people who depend on it.
The Connected Systems
| Spoke | System | What it brings |
|---|---|---|
| whk-wms | warehouse management | inventory, movements, receipts; 14 data sources |
| forge-mes | manufacturing execution (the interim bridge today, the Go module to come) | orders, batches, recipes, changeover, audit; 18 sources |
| whk-cmms | maintenance management | equipment, work orders, maintenance events |
| whk-erpi | ERP integration (NetSuite) | master data, orders, finance |
| whk-nms | network management | the plant network's topology and health |
| bosc-ims | aerospace inventory | parts and stock over gRPC |
| next-trend | time-series historian | archived process history, bulk backfill |
| scanner-gateway | Android barcode scanners | scans as events |
| ot-module | the plant floor: OPC-UA, MQTT, alarms, control writes, scripting | tags, alarms, writes; 21 sources |
Vendor SCADA (Ignition) runs in parallel behind a bridge while the OT module proves parity; Jython middleware scripts are being migrated to the Forge scripting SDK.
Speaker notes
What a Contract Means to You
Each spoke has a FACTS specification: what the system is, what it is allowed to do (read, be written to, backfill, subscribe), how it connects, what data it provides, how each field maps to Forge context, and what happens on errors.
- The spec is the contract. If the spoke does not match its spec, it cannot connect.
- Approval state is visible:
forge governance specsshows whether each contract is approved by the owner, pending review after a change, or modified without review. - A change on either side fails the gate before it fails production. If a vendor upgrade changes the data a system sends, the contract check catches it in the hub, not on the floor.
| Contract | State today |
|---|---|
| all nine: whk-wms, forge-mes, bosc-ims, whk-cmms, whk-erpi, whk-nms, next-trend, scanner-gateway, ot-module | approved by the owner on 2026-11-13, after every contract gained its time-governance declaration |
| ot-module | approved, but its contract still fails schema validation until the OT vocabulary is extended (FB-079; decided 2026-11-03) |
Speaker notes
- "Approved" means the owner approved this exact content. A contract goes back to pending whenever its content changes (a person or an AI agent re-stamps it) and the owner re-approves; "pending" does not mean broken.
U5 · The Plant Floor
Nav: ← U4 · ⇤ TOC · ⇅ Landing fork · U6 →
Tags, alarms, writes and changeover: how Forge reaches equipment, and why a screen can ask for a write but never make one.
Tags
- A tag is a named value from the floor: a temperature, a valve state, a counter. Forge reads tags through OPC-UA and keeps them in a tag engine with eight kinds of source: direct reads, scheduled polls, in-memory values, calculated expressions, SQL queries, virtual and derived values, and events.
- Every tag value carries a quality: good, bad or uncertain; a bad value is shown as bad, never as a plausible number.
- Tags carry context: the equipment and area they belong to, the lot and operating mode at the time.
- Tag paths are normalised across OPC-UA, Ignition and Forge, so a tag keeps its identity through a migration.
Speaker notes
- Honest: since 2026-11-13 a tag's source time on OPC UA is corrected to the master clock by the server's measured offset, with the stamp as sent and the offset kept on the record, and a value without a time is refused rather than given the poll time. Refusing a device whose clock cannot be read is the next step (FB-093).
Alarms
- Alarms follow the ISA-18.2 standard: the states above plus "suppressed by design" and "out of service"; nine alarm types (high, high-high, low, low-low, digital, rate of change, quality, communication, custom).
- Every alarm event is journaled; active alarms and history are available to screens and to other systems: an alarm can publish to the plant message bus, and a maintenance alarm can open a CMMS work order automatically.
- How alarms look (colours, sounds, priority) is the screen layer's job from a declared contract, the same on every screen.
Speaker notes
src/forge/modules/ot/alarming; presentation follows ISA-101 in forge-display when it exists.
Writing to Equipment · From the Operator Seat
- A screen asks; the core decides. No path exists from any interface to a PLC that does not pass validation, review, interlocks, authorization, write with read-back, and audit.
- Some tags require two-step review: the core shows you the current value and gives you a one-time token; the commit must present the token and a reason from the site's own list.
- Interlocks block writes when a condition is unsafe; only an administrator can bypass one, with a reason that is recorded.
- Every write is reconstructible from the audit log: who, what, when, which interlocks were evaluated, what the equipment read back.
- Whether a screen may write at all depends on the kind of screen: a desktop HMI may; a web page or a phone may not.
Speaker notes
- Multi-party approval (two people) for certain writes is designed; the role model it needs is signed (D-1, 2026-11-03) and FB-075 builds it.
Changeover
- The OT module runs the MES changeover sequence: the recipe from the manufacturing system becomes a batch of PLC writes, each through the defense chain, driven by the CIP runner against the PLC.
- Operators confirm start, retry a recipe, resume or restart a connection through hub endpoints that require the right scope; the hub user is recorded as the actor on the MES write, the audit record and the events.
- Vendor SCADA can run in parallel during a migration: the bridge polls the vendor system and the dual-write validator proves the two agree before a cut-over.
Speaker notes
- Today the manufacturing system on the other side is the interim MES bridge; the Go forge-mes module takes over the changeover later.
Three Layers of Control Above the PLC
| Layer | What it does | Who or what acts |
|---|---|---|
| PC-L1 | the PID control your PLC runs today; it stays in the PLC | the controls engineer; the PLC |
| PC-L2 | model-predictive control for the complex loops: holds them steady and acts on a disturbance before it shows in the process; improves its own model and tuning under rules you set | the MPC Supervisor, a Forge module, writing through the same defense chain as every other write |
| PC-L3 | expert agents that learn all the processes of an area and work on the whole toward goals you state (for example, 130,000 barrels a year into the warehouses); every number they use comes from a deterministic tool, so it can be checked | the agents, acting only through PC-L2 |
What never changes, whatever is switched on:
- You can always take over. A loop leaves MPC mode from the plant's own HMI, immediately, with Forge up or down.
- Nothing writes to a safety system, and nothing bypasses an interlock. The PLC clamps every value the upper layers write.
- No layer writes PLC code. It can recommend; an engineer decides.
- Everything starts Off. Each kind of automatic change begins as a proposal a person approves; it earns autonomy only after it has proved itself for a period you define, against figures you enter, and it loses that autonomy by itself if its record slips. If PC-L2 goes offline, PC-L3 can only write recommendations.
Where it stands: the owner decided the framework on 2026-11-13; nothing of it is built yet, and nothing will be before its specifications are written.
Speaker notes
U6 · Context, Products and Decisions
Nav: ← U5 · ⇤ TOC · ⇅ Landing fork · U7 →
Why "area" means one thing everywhere, where a figure comes from, and how a decision is recorded so its cost can be learned.
Context · Why Area Means One Thing
- A value like
TIT_2010 = 61.2is useless until you know it is Cooker 01's temperature, in the Granary area, during lot L-2026-0412, on the night shift, in Cooking mode. Historians store values; context used to live in people's heads. - In Forge, context is declared per spoke (which source field is the equipment, which is the lot) and defined once for the whole platform in a manufacturing entity catalogue following the ISA-95 hierarchy: enterprise, site, area, line, cell, equipment; material items, lots, production orders.
- The hub enriches what the source cannot say: the shift from the timestamp, the area from the location, the lot from the active batch.
- A record missing required context is not stored silently; what is required is declared per spoke and checked by its contract.
Speaker notes
docs/core/manufacturing-entity-catalog.md; the Context Engine serves the vocabulary under/v1/context.
Data Products · Where a Figure Comes From
| A data product has | So that |
|---|---|
| a version | consumers know which definition they are reading |
| a quality objective | "good" is stated, and shown beside every figure |
| lineage | each figure traces back through each transformation to the raw records |
| a curation recipe | the hub builds and runs the same pipeline on every new record |
| an owner and a status | somebody answers for it; draft, published, deprecated |
Normalisation happens before comparison: units are converted, time is aligned, and a comparison declares its basis or says "unnormalised". Aggregate views link to the segmented views beneath them, so a trend cannot hide the operating condition that explains it.
Speaker notes
docs/VISION.mdP-3; the research basis on decision error isdocs/PRINCIPLES.md§4.
Recording a Decision
A confidently wrong decision costs more than the data problem that caused it, and its cost is spread across many shifts and units. Forge treats the decision as a record.
For significant decisions (capital allocation, process changes, root-cause conclusions, vendor selection, quality dispositions) the system records a minimum frame: what is being decided and why now; the current hypothesis with evidence links; challenging evidence, required; alternative hypotheses; key assumptions with a confidence; missing information; risk if wrong; opportunity if right; existing controls and evidence they work, required; a reassessment trigger; and a named owner.
- Every assumption is tracked; new data that contradicts one alerts its owner and the owners of every decision that relied on it.
- Outcomes are observed against the decision, so what was known, what was decided and what happened can be replayed.
Where it stands: the decision and assumption models exist in the hub; the decision-support workflow around them is not built yet.
Speaker notes
docs/PRINCIPLES.md§4;docs/VISION.mdP-9.
U7 · Governance for Users
Nav: ← U6 · ⇤ TOC · ⇅ Landing fork · U8 →
What "approved" means, why nothing changes silently, and the owner's role.
Contracts, Not Promises
- Every interface in Forge is a specification: what a spoke may do, what a hub route returns, what a screen shows and which action needs which role, how transport is secured.
- The specification is checked by a runner and enforced as a gate: a change that breaks a contract is stopped before it is merged, not discovered on the floor.
- Specifications are hashed. Each carries its hash, its state and a history of who or what changed it.
| State | Meaning |
|---|---|
approved |
the owner approved this exact content |
pending_review |
the content was changed (by a person or an AI agent) and re-stamped; it awaits the owner |
modified |
the content no longer matches its hash; nothing trusts it until it is stamped and approved |
reverted |
rolled back to a previous approved hash |
- Only the owner approves. AI coding agents working on the platform can propose and stamp; they can never approve, and the hub checks the hash before trusting a contract.
Speaker notes
docs/FxTS/README.mdanddocs/PRINCIPLES.md§3; the command isforge governance specs --pending.
Why This Matters to You
- A spoke whose contract was relaxed without approval cannot register.
- A route that stopped returning what its contract says fails the build.
- A screen that tries to write from a profile that may not fails the view contract.
- The platform's own engineering is governed the same way: one item per change, every finding recorded, documents current before every change ships, owner-only approvals, and a governed memory for the AI agents that work on the code.
Speaker notes
- Problem P-7 in
docs/VISION.md: the more AI assistance a team uses, the more the contracts must be machine-enforced.
- Problem P-7 in
U8 · Screens
Nav: ← U7 · ⇤ TOC · ⇅ Landing fork · U9 →
What you will look at, and what you look at today.
One Renderer, Four Kinds of Screen
In the finished system no module ships its own screens. A module describes what it has (points with units and ranges, alarms, actions with the role and confirmation each needs, surfaces) and forge-display renders it on four profiles:
| Profile | Rate | May write? | Alarms |
|---|---|---|---|
| desktop HMI (the control room, kiosk) | 20 Hz | yes | all operations |
| desktop app | 10 Hz | no | acknowledge only |
| web | 4 Hz | no | view |
| mobile | 1 Hz | no | view |
- A module may make a screen stricter than the baseline, never looser.
- Stale values are marked, bad quality is shown, alarms are annunciated and styled by one standard (ISA-101), and every action shows its result with the audit confirmation.
Speaker notes
docs/VISION.mdP-8 and §3.4; the contract is FVTS.
What You Look at Today · Honest
- forge-display does not exist yet. Its contract (FVTS), the checker, a render-profile baseline, a reference renderer and example messages do; its open questions were answered by the owner on 2026-11-03 (D-4), so the renderer's design is next.
- The manufacturing system's screens today are the interim MES bridge's own web frontend, imported with it; they will be retired when forge-display renders the MES surfaces.
- Plant-floor screens today are the vendor's (Ignition) where a site keeps them; the OT module serves the data behind them and its REST interfaces.
U9 · Identity, Roles and Credentials
Nav: ← U8 · ⇤ TOC · ⇅ Landing fork · U10 →
Who may do what, where, and how systems get their credentials.
Identity and Roles
- Your installation chooses how people sign in (single sign-on with OpenID Connect, local accounts, LDAP or Active Directory, SAML), and Forge decides what a signed-in identity may do.
- Roles are scoped: a role says what you may do in which area, on which equipment, in which module. "Operators in the distillery may acknowledge alarms there and see nothing from the ERP" is a configuration, not a program.
- Roles constrain what you can read as well as what you can do.
- Separation of duties is evaluated by the hub: two-step review on a write, an interlock bypass with a recorded reason, approvals.
- In a multi-site enterprise, roles are assigned at the managing hub and inherited by sites; a site keeps verifying sign-ins while the link to headquarters is down.
Where it stands: the role model is decided and signed (2026-11-03); the hub's authentication is off by default in development, and scoped roles on every route are not yet enforced (FB-075).
Speaker notes
docs/decisions/roles.md(R-1 … R-19, signed 2026-11-03);docs/WHERE-WE-ARE.md§3.10.
Credentials
- The hub owns the databases. A module never carries a database password it created itself: the hub grants a module access to its own schema and hands it a credential that is printed once and never stored; re-issuing rotates it.
- Hub ↔ spoke traffic is encrypted both ways with certificates, and each spoke has its own token.
- Every grant, every issued credential and every refusal is in the hub's access audit.
Speaker notes
forge db accessin U3; the design isdocs/DB_ORCHESTRATION_FRAMEWORK.md.
U10 · Operations
Nav: ← U9 · ⇤ TOC · ⇅ Landing fork · U11 →
How a site is run, upgraded and, in time, backed up.
Running a Site · Honest
| Concern | Today | Planned |
|---|---|---|
| Deployment | Docker Compose, development only | Kubernetes per hub (P-12) |
| Health | /v1/health probes every component; /readyz |
service-level objectives and alerts (FOTS) |
| Upgrades | forge migrate up applies versioned database migrations; a migration is never edited after it is applied |
an upgrade procedure per hub |
| Backups | none | scheduled backups of every store and a restore procedure |
| Clock | offsets measured and warned; device time corrected on OPC UA; every connected system declares how it keeps time (2026-11-13) | a clock outside its tolerance is refused (FB-093, D-9) |
| Multi-site | one hub | hub of hubs with upward audit and offline operation (M6) |
- "Solved when": a site hub can be stood up, upgraded and restored from backup by procedure, and its objectives are visible.
Speaker notes
docs/WHERE-WE-ARE.md§3.11; the K8s decision is recorded as owner's note.
U11 · Where to Go Next
Nav: ← U10 · ⇤ TOC · ⇅ Landing fork
| If you want to… | Open |
|---|---|
| read the full definition and the problems it solves | docs/VISION.md |
| see what exists today, component by component | docs/WHERE-WE-ARE.md |
| see the route and what gates it | docs/WHERE-WE-ARE-GOING.md |
| understand a contract family | docs/FxTS/<FRAMEWORK>.md |
| see which contracts await approval | forge governance specs --pending |
| ask for a change or report a problem | a row in BACKLOG.md: every finding is recorded, never skipped |
| see the decisions the owner is weighing | docs/ROADMAP.md §5 and docs/decisions/ |
Thank you. Return to the landing fork ↑ · Start the Software Dev path ↑
Speaker notes
- The end-user path is complete for operators by design: nothing above sends you into the dev path for a topic.
Glossary
Every acronym used in this tutorial, with its expansion. Each acronym occurrence after the first in the body text is a link to its entry here. Use the floating ← Return to Previous button at the top-right of the viewport to jump back to where you were reading.
- AI
- Artificial Intelligence
- API
- Application Programming Interface
- CI
- Continuous Integration
- CIP
- Common Industrial Protocol
- CLI
- Command-Line Interface
- CMMS
- Computerized Maintenance Management System
- CSV
- Comma-Separated Values
- DDL
- Data Definition Language
- DV
- Disturbance Variable
- ERP
- Enterprise Resource Planning
- FACTS
- Forge Adapter Conformance Test Specification
- FATS
- Forge API Test Specification
- FDTS
- Forge Data Test Specification
- FHTS
- Forge Hash Test Specification
- FLTS
- Forge Lineage Test Specification
- FNTS
- Forge Normalization Test Specification
- FOTS
- Forge Observability Test Specification
- FPTS
- Forge Performance Test Specification
- FQTS
- Forge Quality Test Specification
- FSD
- Functional Specification Document
- FSTS
- Forge Security Test Specification
- FTTS
- Forge Transport Test Specification
- FVTS
- Forge View Test Specification
- FxTS
- Forge Test Specification
- HMI
- Human-Machine Interface
- HTML
- HyperText Markup Language
- JSON
- JavaScript Object Notation
- LDAP
- Lightweight Directory Access Protocol
- MDEMG
- Multi-Dimensional Emergent Memory Graph
- MES
- Manufacturing Execution System
- MPC
- Model Predictive Control
- MQTT
- Message Queuing Telemetry Transport
- MV
- Manipulated Variable
- NTP
- Network Time Protocol
- OPC
- Open Platform Communications
- OT
- Operational Technology
- PID
- Proportional-Integral-Derivative
- PLC
- Programmable Logic Controller
- PR
- Pull Request
- PTP
- Precision Time Protocol
- PV
- Process Variable
- QMS
- Quality Management System
- RBAC
- Role-Based Access Control
- REST
- Representational State Transfer
- SAML
- Security Assertion Markup Language
- SCADA
- Supervisory Control and Data Acquisition
- SDK
- Software Development Kit
- SME
- Subject-Matter Expert
- SP
- Setpoint
- SQL
- Structured Query Language
- TLS
- Transport Layer Security
- TOC
- Table of Contents
- UDT
- User-Defined Type
- UI
- User Interface
- UTC
- Coordinated Universal Time
- WAN
- Wide Area Network
- WMS
- Warehouse Management System
- gRPC
- gRPC Remote Procedure Calls
- mTLS
- mutual Transport Layer Security