c3ab37523a
Configuration is now adopted across all three sister apps (local branches), so flip the status lines in CLAUDE.md, components/configuration/GAPS.md, and the lib README/CLAUDE.md from 'not adopted' to adopted (also corrects 27->42 tests). Adds the brainstorm design doc + bite-sized implementation plan (+tasks.json) under docs/plans/ that drove the adoption.
295 lines
22 KiB
Markdown
295 lines
22 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## What this repository is
|
|
|
|
`scadaproj` is primarily an umbrella/index workspace that aggregates a family of
|
|
related SCADA / OT / Wonderware / OPC UA "sister projects" that live as **sibling
|
|
directories under `~/Desktop/`**. It now also **hosts five pieces of source itself** —
|
|
the shared [`ZB.MOM.WW.Auth/`](ZB.MOM.WW.Auth/) library, the shared
|
|
[`ZB.MOM.WW.Theme/`](ZB.MOM.WW.Theme/) UI kit, the shared
|
|
[`ZB.MOM.WW.Health/`](ZB.MOM.WW.Health/) health-check library, the shared
|
|
[`ZB.MOM.WW.Telemetry/`](ZB.MOM.WW.Telemetry/) observability library, and the shared
|
|
[`ZB.MOM.WW.Configuration/`](ZB.MOM.WW.Configuration/) config-validation library — all the realized output of their
|
|
respective component normalizations (see [Component normalization](#component-normalization)).
|
|
The point of this file is to give a high-level scan of each sister project — its purpose,
|
|
location, stack, and primary commands — so a fresh Claude Code session can orient across
|
|
the whole family without opening each repo first.
|
|
|
|
Each sister project keeps its own authoritative `CLAUDE.md`. This index is a
|
|
**summary of those files**; when you actually work in a project, open that project's
|
|
own `CLAUDE.md` for the full picture. See [Refreshing this index](#refreshing-this-index).
|
|
|
|
> The project list below is **curated manually**. Add or remove entries as the family
|
|
> changes — do not assume every directory under `~/Desktop/` belongs here.
|
|
|
|
## Sister projects (core SCADA/OT family)
|
|
|
|
### Runtime / implementation (active code)
|
|
|
|
| Project | Location | Stack | Repo | Summary |
|
|
|---|---|---|---|---|
|
|
| **OtOpcUa** | `~/Desktop/OtOpcUa` | .NET 10, OPC UA, gRPC | `gitea.dohertylan.com/dohertj2/lmxopcua` | OPC UA server that exposes AVEVA System Platform (Wonderware) Galaxy tags as an OPC UA address space. Galaxy access flows through an in-process `GalaxyDriver` → gRPC → the **mxaccessgw** gateway. |
|
|
| **MxAccessGateway** (`mxaccessgw`) | `~/Desktop/MxAccessGateway` | .NET 10 gateway (x64) + .NET 4.8 worker (**x86**), gRPC | `gitea.dohertylan.com/dohertj2/mxaccessgw` | gRPC gateway giving modern clients full MXAccess parity without loading 32-bit COM. Two-process: gateway (ASP.NET Core gRPC + Blazor dashboard) + per-session x86 worker that owns the MXAccess COM STA. **OtOpcUa depends on this.** |
|
|
| **ScadaBridge** | `~/Desktop/ScadaBridge` | .NET 10, Akka.NET, Docker | _git_ | Full implementation of the distributed SCADA platform — hub-and-spoke (1 central cluster + N site clusters). Projects prefixed `ZB.MOM.WW.ScadaBridge.*`; solution `ZB.MOM.WW.ScadaBridge.slnx`. Ships `src/`, `tests/`, `docker/` topology, and the design docs that are the spec. |
|
|
|
|
## Cross-project relationships
|
|
|
|
The three indexed projects are **separate repos and separate processes**, coupled at
|
|
**runtime over wire protocols (gRPC + OPC UA)** — not by project/compile references. They
|
|
share the `ZB.MOM.WW.*` product namespace (`ZB.MOM.WW.OtOpcUa.*`, `ZB.MOM.WW.ScadaBridge.*`;
|
|
the gateway uses `MxGateway.*`). The common subject is **AVEVA System Platform (Wonderware)
|
|
"Galaxy"** data, and `mxaccessgw` is the linchpin that the other two connect through.
|
|
|
|
### Data flow
|
|
|
|
```
|
|
AVEVA System Platform — Wonderware "Galaxy"
|
|
(OT source of truth: runtime tags + Galaxy Repository SQL DB)
|
|
▲
|
|
│ MXAccess COM (32-bit, STA message pump)
|
|
│
|
|
┌────────────────┴─────────────────┐
|
|
│ MxAccessGateway (mxaccessgw) │ gateway x64 .NET10 + worker x86 net48
|
|
│ gRPC service; OWNS the 32-bit │ protos: mxaccess_gateway / mxaccess_worker
|
|
│ COM bitness + STA pump │ / galaxy_repository
|
|
└──────┬─────────────────────┬──────┘
|
|
gRPC (MxCommand/MxEvent + │ gRPC (ScadaBridge "MxGateway" adapter:
|
|
GalaxyRepository browse) │ native MxAccess data + A&C alarms)
|
|
│ │
|
|
┌─────┴──────┐ │
|
|
│ OtOpcUa │ GalaxyDriver maps │
|
|
│ OPC UA srv │ Galaxy hierarchy → │
|
|
│ (.NET 10) │ OPC UA addr space │
|
|
└─────┬──────┘ │
|
|
│ OPC UA (opc.tcp; data + A&C alarms)
|
|
▼ ▼
|
|
┌──────────────────────────────────────────────┐
|
|
│ ScadaBridge — Data Connection Layer (DCL) │
|
|
│ OPC UA adapter │ MxGateway adapter │ custom │
|
|
└─────────────────────────┬────────────────────┘
|
|
▼
|
|
Instance Actors → site clusters → central cluster / UI
|
|
```
|
|
|
|
### Edge-by-edge
|
|
|
|
- **MxAccessGateway is the foundation.** It is the *only* component that loads 32-bit
|
|
MXAccess COM (its x86 net48 worker owns the COM apartment + STA pump). It exposes that to
|
|
modern x64/.NET-10 callers over gRPC, and also serves Galaxy Repository SQL browse RPCs.
|
|
This is *why* the other two exist as .NET 10 / x64 and never touch COM directly.
|
|
- **OtOpcUa → MxAccessGateway** (gRPC client). OtOpcUa's in-process `GalaxyDriver`
|
|
(`src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/`) uses two gateway channels: the
|
|
`GalaxyRepositoryClient` for the static hierarchy, and an MXAccess session
|
|
(`MxCommand`/`MxEvent` protos) for live read/write/subscribe. A `DeployWatcher` polls the
|
|
gateway's deploy-event signal to rebuild the OPC UA address space on Galaxy redeploy.
|
|
OtOpcUa's job is purely a **protocol bridge**: it republishes Galaxy as an OPC UA address
|
|
space for *any* OPC UA client.
|
|
- **ScadaBridge → OPC UA** (OPC UA client). ScadaBridge's DCL has an OPC UA adapter that
|
|
collects data and mirrors native OPC UA Alarms & Conditions. OtOpcUa is exactly such a
|
|
server, so ScadaBridge can ingest Wonderware data **indirectly via OtOpcUa**.
|
|
- **ScadaBridge → MxAccessGateway** (gRPC client). The DCL *also* has a dedicated
|
|
**MxGateway adapter** that talks to `mxaccessgw` directly for native MxAccess data and
|
|
alarms — so ScadaBridge can reach Wonderware data **directly, bypassing OtOpcUa**.
|
|
Both adapters implement the same `IAlarmSubscribableConnection` seam, and a read-only
|
|
`NativeAlarmActor` unifies OPC-UA-A&C and MxAccess alarms onto one condition model.
|
|
|
|
### Net effect
|
|
|
|
- `mxaccessgw` is a shared dependency of **both** OtOpcUa and ScadaBridge.
|
|
- ScadaBridge has **two paths** to the same Wonderware data: (1) OPC UA → OtOpcUa →
|
|
gateway, or (2) MxGateway adapter → gateway directly. Path 1 gives standards-based OPC UA
|
|
decoupling; path 2 gives a more direct/native feed.
|
|
- Coupling is loose: each repo references the others only as **sibling context** (the
|
|
`## Sister Projects` note in ScadaBridge's own `CLAUDE.md` lists `MxAccessGateway` and
|
|
`OtOpcUa` with their Gitea URLs but states they are *not part of its solution*).
|
|
- **The break surface is the wire contracts, not code.** Because coupling is by network
|
|
protocol, the things that break across repo boundaries are: the gateway's `.proto` files
|
|
(`mxaccess_gateway.proto`, `mxaccess_worker.proto`, `galaxy_repository.proto`), and the
|
|
OPC UA address-space shape OtOpcUa publishes (browse paths, node IDs, A&C alarm model).
|
|
Changes to any of these must be coordinated across the affected repos — a green build in
|
|
one repo does not prove the others still interoperate.
|
|
|
|
## Component normalization
|
|
|
|
Because the sister repos re-implement the same cross-cutting concerns separately and drift
|
|
apart, [`components/`](components/) normalizes them: per component, the **one target** spec,
|
|
each project's **code-verified current state**, and the **gaps** between. See
|
|
[`components/README.md`](components/README.md) for the convention and workflow.
|
|
|
|
| Component | Status | Goal | Design | Implementation |
|
|
|---|---|---|---|---|
|
|
| Auth (login / identity / authz) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Auth` lib | [`components/auth/`](components/auth/) | [`ZB.MOM.WW.Auth/`](ZB.MOM.WW.Auth/) |
|
|
| UI Theme (layout / tokens / components) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Theme` RCL | [`components/ui-theme/`](components/ui-theme/) | [`ZB.MOM.WW.Theme/`](ZB.MOM.WW.Theme/) |
|
|
| Health (readiness / liveness / active-node) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Health` lib | [`components/health/`](components/health/) | [`ZB.MOM.WW.Health/`](ZB.MOM.WW.Health/) |
|
|
| Observability (metrics / traces / logs) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Telemetry` lib + `.Serilog` | [`components/observability/`](components/observability/) | [`ZB.MOM.WW.Telemetry/`](ZB.MOM.WW.Telemetry/) |
|
|
| Config + validation (options / startup validation) | Adopted (lib `0.1.0`; all 3 apps, local) | Shared `ZB.MOM.WW.Configuration` lib | [`components/configuration/`](components/configuration/) | [`ZB.MOM.WW.Configuration/`](ZB.MOM.WW.Configuration/) |
|
|
| Audit (event model + writer seam) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Audit` lib | [`components/audit/`](components/audit/) | [`ZB.MOM.WW.Audit/`](ZB.MOM.WW.Audit/) |
|
|
|
|
The auth component is fully populated: a normalized [`spec`](components/auth/spec/SPEC.md), a
|
|
proposed [`shared-contract`](components/auth/shared-contract/ZB.MOM.WW.Auth.md), three
|
|
[`current-state`](components/auth/current-state/) docs, and an adoption [`GAPS`](components/auth/GAPS.md)
|
|
backlog. Common ground = LDAP/GLAuth identity + peppered-HMAC API keys; left per-project =
|
|
the authz vocabularies (OPC-UA permissions / gRPC scopes / roles + site-scoping).
|
|
|
|
The shared library is **built and lives in this repo** at [`ZB.MOM.WW.Auth/`](ZB.MOM.WW.Auth/)
|
|
(its own nested git repo; .NET 10; 4 packages — `Abstractions`, `Ldap`, `ApiKeys`, `AspNetCore`;
|
|
172 tests; `dotnet pack` → 4 nupkgs @ 0.1.0). The implementation plan is at
|
|
[`docs/plans/2026-06-01-zb-mom-ww-auth-shared-library.md`](docs/plans/2026-06-01-zb-mom-ww-auth-shared-library.md).
|
|
**Not yet adopted** by the three apps — that's the follow-on tracked in [`components/auth/GAPS.md`](components/auth/GAPS.md) (#8).
|
|
Build/test from `ZB.MOM.WW.Auth/`: `dotnet test`. Consumer matrix: OtOpcUa → Abstractions+Ldap+AspNetCore;
|
|
MxAccessGateway & ScadaBridge → all four (ApiKeys not used by OtOpcUa).
|
|
|
|
The UI-theme component is fully populated: a normalized [`spec`](components/ui-theme/spec/SPEC.md),
|
|
a [`design-tokens`](components/ui-theme/spec/DESIGN-TOKENS.md) reference, a
|
|
[`shared-contract`](components/ui-theme/shared-contract/ZB.MOM.WW.Theme.md), three
|
|
[`current-state`](components/ui-theme/current-state/) docs, and an adoption [`GAPS`](components/ui-theme/GAPS.md)
|
|
backlog. Shared = Technical-Light tokens + IBM Plex fonts + side-rail shell + widgets; left
|
|
per-project = each app's `site.css` page layout, route content, scoped `.razor.css`.
|
|
|
|
The shared RCL is **built and lives in this repo** at [`ZB.MOM.WW.Theme/`](ZB.MOM.WW.Theme/)
|
|
(.NET 10 Razor Class Library; single package; 32 bUnit tests; `dotnet pack` → 1 nupkg @ 0.1.0).
|
|
The implementation plan is at
|
|
[`docs/plans/2026-06-01-zb-mom-ww-theme-shared-library.md`](docs/plans/2026-06-01-zb-mom-ww-theme-shared-library.md).
|
|
**Not yet adopted** by the three apps — that's the follow-on tracked in [`components/ui-theme/GAPS.md`](components/ui-theme/GAPS.md).
|
|
Build/test from `ZB.MOM.WW.Theme/`: `dotnet test`. Consumer matrix: all three apps consume
|
|
the single `ZB.MOM.WW.Theme` package (OtOpcUa AdminUI, MxGateway Server, ScadaBridge Host + CentralUI).
|
|
|
|
The health component is fully populated: a normalized [`spec`](components/health/spec/SPEC.md), a
|
|
[`shared-contract`](components/health/shared-contract/ZB.MOM.WW.Health.md), three
|
|
[`current-state`](components/health/current-state/) docs, and an adoption [`GAPS`](components/health/GAPS.md)
|
|
backlog. Shared = three-tier endpoint convention (ready/active/healthz) + canonical JSON writer +
|
|
`IActiveNodeGate` seam + `GrpcDependencyHealthCheck` + `AkkaClusterHealthCheck` + `ActiveNodeHealthCheck`
|
|
+ `DatabaseHealthCheck<TContext>`; left per-project = which probes each app registers,
|
|
orchestrator wiring, and ScadaBridge's distributed health-monitoring pipeline.
|
|
|
|
The shared library is **built and lives in this repo** at [`ZB.MOM.WW.Health/`](ZB.MOM.WW.Health/)
|
|
(.NET 10; 3 packages — `ZB.MOM.WW.Health`, `ZB.MOM.WW.Health.Akka`, `ZB.MOM.WW.Health.EntityFrameworkCore`;
|
|
58 tests; `dotnet pack` → 3 nupkgs @ 0.1.0).
|
|
**Not yet adopted** by the three apps — that's the follow-on tracked in [`components/health/GAPS.md`](components/health/GAPS.md).
|
|
Build/test from `ZB.MOM.WW.Health/`: `dotnet test`. Consumer matrix: MxAccessGateway → core only;
|
|
OtOpcUa & ScadaBridge → all three packages.
|
|
|
|
The observability component is fully populated: a normalized [`spec`](components/observability/spec/SPEC.md),
|
|
a [`metric-conventions`](components/observability/spec/METRIC-CONVENTIONS.md) reference, a
|
|
[`shared-contract`](components/observability/shared-contract/ZB.MOM.WW.Telemetry.md), three
|
|
[`current-state`](components/observability/current-state/) docs, and an adoption [`GAPS`](components/observability/GAPS.md)
|
|
backlog. Shared = OTel Resource (service.name/site.id/node.role identity triple) + standard instrumentation
|
|
(ASP.NET Core, HttpClient, gRPC client, runtime, process) + Prometheus always-on exporter + OTLP opt-in
|
|
+ Serilog two-stage bootstrap + SiteId/NodeRole/NodeHostname enrichers + TraceContextEnricher (trace_id/span_id)
|
|
+ ILogRedactor seam; left per-project = application Meters/ActivitySources, sink config, per-operation
|
|
enrichers, and redaction policies.
|
|
|
|
The shared library is **built and lives in this repo** at [`ZB.MOM.WW.Telemetry/`](ZB.MOM.WW.Telemetry/)
|
|
(.NET 10; 2 packages — `ZB.MOM.WW.Telemetry`, `ZB.MOM.WW.Telemetry.Serilog`; 19 tests;
|
|
`dotnet pack` → 2 nupkgs @ 0.1.0). **Adopted across all three apps on 2026-06-01** (branch
|
|
`feat/adopt-zb-telemetry` per repo, behaviour-preserving): `AddZbTelemetry` (Resource + standard
|
|
instrumentation + Prometheus `/metrics`) everywhere; OtOpcUa + MxGateway on `AddZbSerilog` (MxGateway's
|
|
MEL→Serilog migration + metrics export both landed in this pass — they were *not* actually done
|
|
beforehand despite an earlier claim); ScadaBridge keeps its `LoggerConfigurationFactory` (min-level
|
|
governance) and only adds the shared `TraceContextEnricher`. Deferred: MxGateway `ms`→`s` + Meter
|
|
rename, ScadaBridge app instruments + Site-node HTTP/1.1 metrics listener, OTLP wiring. Per-repo
|
|
result tracked in [`components/observability/GAPS.md`](components/observability/GAPS.md).
|
|
Build/test from `ZB.MOM.WW.Telemetry/`: `dotnet test`. Consumer matrix: all three apps consume both
|
|
packages after adoption (OtOpcUa, MxGateway Server, ScadaBridge Host + any instrumented project).
|
|
|
|
The configuration component is fully populated: a normalized [`spec`](components/configuration/spec/SPEC.md), a
|
|
[`shared-contract`](components/configuration/shared-contract/ZB.MOM.WW.Configuration.md), three
|
|
[`current-state`](components/configuration/current-state/) docs, and an adoption [`GAPS`](components/configuration/GAPS.md)
|
|
backlog. Shared = the `IValidateOptions<T>` failure-accumulation base (`OptionsValidatorBase<T>`) +
|
|
reusable rule primitives (`ValidationBuilder`: port / host:port / required / positive-duration / one-of /
|
|
min-count) + `AddValidatedOptions<TOptions,TValidator>()` (bind + validate + `ValidateOnStart`) + the
|
|
pre-host `ConfigPreflight` aggregator (generalizes ScadaBridge's `StartupValidator`, byte-compatible
|
|
message); left per-project = each app's options classes + domain rules, and OtOpcUa's
|
|
draft/generation-content validation (DB-side `sp_ValidateDraft`; its C# `DraftValidator` is dormant).
|
|
|
|
The shared library is **built and lives in this repo** at [`ZB.MOM.WW.Configuration/`](ZB.MOM.WW.Configuration/)
|
|
(.NET 10; single package `ZB.MOM.WW.Configuration`; 27 tests; `dotnet pack` → 1 nupkg @ 0.1.0).
|
|
The implementation plan is at
|
|
[`docs/plans/2026-06-01-zb-mom-ww-configuration-shared-library.md`](docs/plans/2026-06-01-zb-mom-ww-configuration-shared-library.md).
|
|
**Adopted across all three apps on 2026-06-01** (OtOpcUa, MxAccessGateway, ScadaBridge) on each repo's
|
|
local default branch (`main`/`master`) — merged, **not yet pushed** to remotes; the package was first
|
|
published to the Gitea feed. Behaviour-preserving onto `OptionsValidatorBase`/`AddValidatedOptions`
|
|
for MxGateway + ScadaBridge (validator messages byte-identical), `StartupValidator` → `ConfigPreflight`
|
|
for ScadaBridge, and net-new `Ldap`/`OpcUa` validators for OtOpcUa. Per-app result tracked in
|
|
[`components/configuration/GAPS.md`](components/configuration/GAPS.md).
|
|
Build/test from `ZB.MOM.WW.Configuration/`: `dotnet test`. Consumer matrix: all three apps consume the
|
|
single package; ScadaBridge is the heaviest adopter (per-module validators + `StartupValidator` →
|
|
`ConfigPreflight`); OtOpcUa adoption is additive (it has no `IValidateOptions` usage today).
|
|
|
|
The audit component is fully populated: a normalized [`spec`](components/audit/spec/SPEC.md), an
|
|
[`event-model`](components/audit/spec/EVENT-MODEL.md) reference, a
|
|
[`shared-contract`](components/audit/shared-contract/ZB.MOM.WW.Audit.md), three
|
|
[`current-state`](components/audit/current-state/) docs, and an adoption [`GAPS`](components/audit/GAPS.md)
|
|
backlog. Common ground = canonical `AuditEvent` record + `AuditOutcome` enum + `IAuditWriter` /
|
|
`IAuditRedactor` seams + helpers (`NullAuditRedactor`, `TruncatingAuditRedactor`, `NoOpAuditWriter`,
|
|
`CompositeAuditWriter`, `RedactingAuditWriter`) + `AddZbAudit` DI registration; left per-project =
|
|
transport/storage and domain vocabulary. Closes the loop on Auth — audit's `Actor` field = the Auth
|
|
principal. `IAuditRedactor` is aligned with Telemetry's `ILogRedactor` seam convention.
|
|
|
|
The shared library is **built and lives in this repo** at [`ZB.MOM.WW.Audit/`](ZB.MOM.WW.Audit/)
|
|
(.NET 10; 1 package — `ZB.MOM.WW.Audit`; only non-BCL dependency `Microsoft.Extensions.DependencyInjection.Abstractions`;
|
|
19 tests; `dotnet pack` → 1 nupkg @ 0.1.0). Repo: `https://gitea.dohertylan.com/dohertj2/zb-mom-ww-audit`.
|
|
**Not yet adopted** by the three apps — that's the follow-on tracked in [`components/audit/GAPS.md`](components/audit/GAPS.md).
|
|
Build/test from `ZB.MOM.WW.Audit/`: `dotnet test`. Consumer matrix: all three apps consume the single
|
|
`ZB.MOM.WW.Audit` package (OtOpcUa, MxAccessGateway, ScadaBridge each map their own audit record/seam
|
|
onto the canonical type at the emit boundary).
|
|
|
|
## Per-project primary commands
|
|
|
|
Run these from inside each project directory (not from `scadaproj`).
|
|
|
|
```bash
|
|
# OtOpcUa
|
|
dotnet build ZB.MOM.WW.OtOpcUa.slnx
|
|
dotnet test ZB.MOM.WW.OtOpcUa.slnx
|
|
dotnet test --filter "FullyQualifiedName~MyTestClass.MyMethod" # single test
|
|
# Docker fixtures run on shared host 10.100.0.35; control via `lmxopcua-fix` (in ~/bin)
|
|
|
|
# MxAccessGateway (PowerShell on Windows)
|
|
dotnet build src/MxGateway.sln
|
|
dotnet build src/MxGateway.Worker/MxGateway.Worker.csproj -p:Platform=x86 # worker MUST be x86
|
|
dotnet test src/MxGateway.Tests/MxGateway.Tests.csproj # no MXAccess needed (fake worker)
|
|
dotnet run --project src/MxGateway.Server/MxGateway.Server.csproj
|
|
|
|
# ScadaBridge (~/Desktop/ScadaBridge)
|
|
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
|
bash docker/deploy.sh # rebuild + redeploy the 8-node cluster
|
|
cd infra && docker compose up -d # local test services (LDAP, SQL, OPC UA, SMTP, REST, Traefik)
|
|
```
|
|
|
|
## Refreshing this index
|
|
|
|
This file is meant to be re-scanned when `scadaproj` is opened in Claude Code:
|
|
|
|
1. List sibling SCADA/OT directories: `find ~/Desktop -maxdepth 2 -iname "claude.md"`.
|
|
2. For each project the user wants indexed, read the **top of its `CLAUDE.md`**
|
|
(project overview + build/run sections) and update its row above.
|
|
3. Keep the project set **curated** — only the SCADA/OT/Wonderware/OPC-UA family belongs here.
|
|
4. Flag new duplicates/overlaps and namespace mismatches rather than silently merging them.
|
|
|
|
## Other workspace projects with a CLAUDE.md (not indexed — promote on request)
|
|
|
|
Listed so they can be pulled into the index above if you decide they belong.
|
|
|
|
**SCADA/OT, de-indexed (still have a `CLAUDE.md` under `~/Desktop/`):**
|
|
|
|
- **OpcUaTestServer** — dual-instance OPC UA test server (.NET 10) for testing OPC UA clients / simulating automation.
|
|
- **scada** (ScadaLink) — design docs + scaffolding for the distributed SCADA platform (`ZB.MOM.ScadaLink.*`).
|
|
- **scadalink-design-opcua-browser** — ScadaBridge variant focused on OPC UA browser / Data Connection Layer work.
|
|
- **DARS** — DARS → Wonderware SCADA migration (design phase, Q2 2026 go-live).
|
|
- **DARS_BU** — backup snapshot of DARS.
|
|
- **plan** — 3-year SCADA IT/OT modernization roadmap (markdown).
|
|
|
|
**Outside the SCADA family:**
|
|
|
|
- **delmia** — DELMIA / Apriso (Intercim Velocity) MES customization export (ASP.NET `.asmx`); MES-adjacent.
|
|
- **lightctrl** — Raspberry Pi Python I/O control (edge hardware).
|
|
- **codestats** — Rust CLI for code statistics on .NET solutions/dirs (dev tooling for the .NET repos).
|
|
- **servecli** — Rust portable SSH/SFTP server for Windows remote task management (greenfield).
|
|
- **JdeScopingTool** — JD Edwards "LotFinder" .NET 4.8 → .NET 10 migration (ERP, not SCADA).
|
|
- **chat** — local-first roleplay chat engine.
|
|
- **candy2** — candy.ai chat scraping / browser automation.
|
|
- **menardslist** — Menards.com cart → printable picklist PDF.
|