Commit Graph

49 Commits

Author SHA1 Message Date
Joseph Doherty 70f91a855a feat(telemetry.serilog): TraceContextEnricher for trace<->log correlation 2026-06-01 07:38:54 -04:00
Joseph Doherty 1344f249d0 feat(telemetry.serilog): AddZbSerilog bootstrap + identity enrichers 2026-06-01 07:38:07 -04:00
Joseph Doherty 3e4d4369bf feat(telemetry): MapZbMetrics Prometheus scrape endpoint 2026-06-01 07:34:26 -04:00
Joseph Doherty 4126e1df54 feat(telemetry): AddZbTelemetry metrics+traces bootstrap 2026-06-01 07:33:51 -04:00
Joseph Doherty 215a646e35 docs(observability): fix metric-convention instrument names + NodeHostname-auto + resolve settled questions
C1: NodeHostname is AUTO throughout. Shared-contract AddZbSerilog doc comment now reads
"SiteId + NodeRole from ZbTelemetryOptions; NodeHostname from Environment.MachineName (auto)".
SPEC.md §0 and §5 prose updated to match. ScadaBridge adoption snippet no longer sets
o.NodeHostname (removed; NodeHostname is auto, not caller-supplied).

C2: METRIC-CONVENTIONS §6.1 OtOpcUa instrument table replaced with code-verified set:
counters otopcua.deploy.applied / driver.lifecycle / virtualtag.eval / scriptedalarm.transition /
opcua.sink.write / redundancy.service_level_change; histogram otopcua.deploy.apply.duration (s);
ActivitySource ZB.MOM.WW.OtOpcUa with spans otopcua.deploy.apply + otopcua.opcua.address_space_rebuild.
Removed invented names (deploy.failed, tag.subscriptions, tag.reads, tag.writes, session.active,
connection.gateway).

C3: METRIC-CONVENTIONS §6.2 MxGateway instrument table replaced with code-verified names from
GatewayMetrics.cs: 13 counters (sessions.opened/closed, commands.started/succeeded/failed,
events.received, queues.overflows, faults, workers.killed/exited, heartbeats.failed,
grpc.streams.disconnected, retries.attempted); 3 histograms ms (workers.startup.duration,
commands.duration, events.stream_send.duration); 4 gauges (sessions.open, workers.running,
events.worker_queue.depth, events.grpc_stream_queue.depth). Removed invented names.

m3: §2 example table replaced mxgateway.session.active + mxgateway.worker.call.duration
(invented) with mxgateway.sessions.open + mxgateway.commands.duration (real). Also fixed
the §2 rule-2 body text example which referenced mxgateway.worker.call.duration.

I4: §5 standard instrumentation table corrected — OtOpcUa now shows  not added for all
five baseline instrumentations, matching current-state/otopcua. All three projects lack
standard instrumentation today; AddZbTelemetry adds it on adoption.

I1+m1: GAPS.md "Decisions still open" — removed the two settled questions (Prometheus-default
and ms→s/meter-rename bundling). Moved them to a new "Decisions settled" section with explicit
resolution notes. One genuinely open question remains (SiteId/NodeRole config binding path).

I2: SPEC.md §5 AddZbSerilog: added note that AddZbSerilog reads Serilog:MinimumLevel from
IConfiguration; callers with a different config key (e.g. ScadaBridge:Logging:MinimumLevel)
apply that override themselves — stays per-project. Shared-contract doc comment updated to match.

I3: MxAccessGateway adoption plan Meters = ["MxGateway.Server"] annotated as temporary with
note to update to ZB.MOM.WW.MxGateway when Gap N1 (Meter-rename) is closed.

m2: SPEC.md §1 now notes AddZbTelemetry also has an IServiceCollection overload for non-standard
hosts, with the IHostApplicationBuilder overload as the primary path.
2026-06-01 07:32:58 -04:00
Joseph Doherty 645388b1f1 feat(telemetry): options + shared OTel Resource 2026-06-01 07:30:54 -04:00
Joseph Doherty a1c3d5ec81 chore: scaffold ZB.MOM.WW.Telemetry solution and projects
Two library projects (ZB.MOM.WW.Telemetry core + Serilog) and two xUnit
test projects; central PM via Directory.Packages.props; dotnet build green.
2026-06-01 07:27:30 -04:00
Joseph Doherty fba3d09eed docs(observability): current-state x3 + GAPS + README
Complete the observability normalization component docs:

- components/observability/current-state/otopcua/CURRENT-STATE.md — full
  OTel SDK (metrics + tracing) + Prometheus; 7 otopcua.* instruments + 2
  spans; Serilog with driver-scope LogContextEnricher; no Resource/service.name
  anywhere; tracing pipeline wired but no exporter; adoption plan: AddZbTelemetry
  gains shared Resource + trace↔log correlation; LogContextEnricher kept bespoke.

- components/observability/current-state/mxaccessgw/CURRENT-STATE.md — 20
  hand-rolled instruments (13 counters, 3 histograms ms-unit, 4 gauges) in
  GatewayMetrics.cs; no OTel SDK → metrics never export; MEL logging with
  GatewayLogScope correlation and GatewayLogRedactor; adoption plan: in-pass
  MEL → AddZbSerilog migration (LogContext correlation, ILogRedactor seam) +
  AddZbTelemetry wires OTel SDK so GatewayMetrics finally exports.

- components/observability/current-state/scadabridge/CURRENT-STATE.md —
  OpenTelemetry.Api is a CVE-patch override only (zero instrumentation); Serilog
  with SiteId/NodeRole/NodeHostname enrichers (strongest set in family); adoption
  plan: replace CVE ref with AddZbTelemetry; adopt AddZbSerilog (LoggerConfigurationFactory
  deleted); add first scadabridge.* instruments.

- components/observability/GAPS.md — divergence table across §1 Resource (P1,
  nobody), §2 metrics export (P1, MxGateway invisible), §3 MxGateway MEL→Serilog
  (P1, in-pass done), §4 trace↔log correlation, §5 ms→s unit, §6 Meter naming,
  §7 standard instrumentation, §8 Serilog version, §9 ScadaBridge zero
  instrumentation; 11-item prioritized backlog.

- components/observability/README.md — overview, per-project status table
  (OTel today / metrics / tracing / logging / enrichers / adoption status),
  normalized vs. left-per-project boundary, 2-package structure, component status.
2026-06-01 07:23:08 -04:00
Joseph Doherty 7d243890ed docs(observability): spec + METRIC-CONVENTIONS + ZB.MOM.WW.Telemetry shared contract
Author the three normalization docs for the observability component:
- components/observability/spec/SPEC.md — Section 0 scope (normalized vs. per-project),
  AddZbTelemetry pipeline, shared Resource attribute set, standard instrumentation baseline,
  exporter conventions, Serilog two-stage bootstrap with identity enrichers and
  TraceContextEnricher, ILogRedactor redaction seam, per-project migration table, and
  acceptance criteria.
- components/observability/spec/METRIC-CONVENTIONS.md — meter naming convention (app
  namespace; MxGateway.Server flagged as convergence target), instrument naming pattern
  (<app>.<subsystem>.<event>), mandatory duration unit = seconds (MxGateway ms histograms
  flagged), Resource attribute set table, standard instrumentation baseline, and per-app
  instrument tables (OtOpcUa 7 instruments + 2 spans; MxGateway 13 counters / 3 histograms
  / 4 gauges; ScadaBridge TBD).
- components/observability/shared-contract/ZB.MOM.WW.Telemetry.md — paper API for the two
  packages: ZbTelemetryOptions, ZbExporter enum, AddZbTelemetry (IHostApplicationBuilder +
  IServiceCollection overloads), ZbResource.Build, MapZbMetrics; AddZbSerilog,
  ZbLogEnricherNames constants, TraceContextEnricher, ILogRedactor, RedactionEnricher.
  Consumer matrix and open contract questions included.
2026-06-01 07:19:38 -04:00
Joseph Doherty 76295695ee docs(health): align shared-contract to shipped API + per-lib CLAUDE.md + cleanup
- Contract: DatabaseHealthCheck<TContext> ctor now shows IServiceProvider (resolves
  IDbContextFactory<TContext> when registered, else a scoped TContext; pool-safe)
- Contract: RequireActiveNode gains retryAfterSeconds = 5 default parameter
- Packages: remove dangling AspNetCore.HealthChecks.UI.Client PackageVersion (no
  csproj referenced it)
- Tests: fix CS8625 in RoleLessCases — use object?[] so null role rows compile
  warning-free under Nullable=enable
- Add ZB.MOM.WW.Health/CLAUDE.md (packages, responsibilities, consumer matrix,
  build/test/pack commands, status + pointer to components/health/)
2026-06-01 07:17:18 -04:00
Joseph Doherty 0c087d150d feat(health): pack ZB.MOM.WW.Health 0.1.0 + README + register health component in indexes
- Added PackageTags to all 3 library csproj files (health-checks;aspnetcore/akka/efcore;scada;wonderware;zb-mom-ww)
- Full solution dotnet test: 58 tests green (32 Akka + 20 core + 6 EFCore)
- dotnet pack -c Release produces ZB.MOM.WW.Health.0.1.0.nupkg, ZB.MOM.WW.Health.Akka.0.1.0.nupkg, ZB.MOM.WW.Health.EntityFrameworkCore.0.1.0.nupkg; artifacts/ not committed
- ZB.MOM.WW.Health/README.md: overview, packages table, consumer matrix, versioning, build/test/pack instructions, status note
- components/README.md: Health row added to component registry
- CLAUDE.md: Health row in Component-normalization table + Health paragraph; intro updated from "two pieces" to "three pieces"
- upcoming.md: Health checks item checked off with pointer to components/health/ and ZB.MOM.WW.Health/
- components/health/README.md: status updated from "Draft / scaffolded / follow-on" to "Built @ 0.1.0"
2026-06-01 07:09:14 -04:00
Joseph Doherty 1c2b23cbbb refactor(health.akka): review polish (internal decision helper, role guard, factory results, test coverage) + fix SPEC §4 gate description 2026-06-01 07:04:29 -04:00
Joseph Doherty edbc79204f refactor(health.ef): review polish (timer release, timeout test, provider disposal, drop unused dep)
- Eagerly call CancelAfter(InfiniteTimeSpan) after a successful probe so the pending OS
  timer is released on the happy path rather than held for the full timeout window.
- Add ProbeTimeout_Unhealthy test: 50 ms timeout with an infinite-blocking probe delegate
  asserts Unhealthy, covering the timeout code path.
- Fix ProbeQueryThrows_Unhealthy to use Task.FromException rather than a synchronous throw,
  accurately modelling a faulted async delegate.
- Wrap all BuildServiceProvider() results in await using so ServiceProvider is disposed
  after each test (no DI provider leak).
- Remove unused Microsoft.EntityFrameworkCore.InMemory package reference; tests use
  SQLite only (InMemory CanConnect semantics differ and the package was not exercised).
- Add <remarks> to DatabaseHealthCheck<TContext> noting the scoped-resolution path is
  safe for AddDbContextPool (scope dispose returns context to pool, not destroys it).
2026-06-01 07:03:16 -04:00
Joseph Doherty aa2251b93d feat(health): core review fixes (async writer, gRPC cancellation, validation, configurable retry-after) 2026-06-01 07:00:21 -04:00
Joseph Doherty cf277eb7df feat(health.akka): active/leader check with role filter + IActiveNodeGate impl 2026-06-01 06:55:46 -04:00
Joseph Doherty 2dbedce0ac feat(health.ef): generic DatabaseHealthCheck<TContext> 2026-06-01 06:48:20 -04:00
Joseph Doherty 25dd328280 feat(health.akka): cluster health check with configurable status policy 2026-06-01 06:47:29 -04:00
Joseph Doherty 1ab2f32e8e feat(health): gRPC dependency health check 2026-06-01 06:44:05 -04:00
Joseph Doherty 5b82d68ea9 feat(health): IActiveNodeGate seam + RequireActiveNode filter 2026-06-01 06:43:11 -04:00
Joseph Doherty d1b837e718 feat(health): canonical JSON health response writer 2026-06-01 06:42:24 -04:00
Joseph Doherty 5fb579c2f0 docs: implementation plan for ZB.MOM.WW.Audit shared library 2026-06-01 06:39:05 -04:00
Joseph Doherty 18be42d0e2 feat(health): scaffold ZB.MOM.WW.Health solution + Task 4 (tags + three-tier MapZbHealth)
Consolidates the library into the scadaproj repo (matching the ZB.MOM.WW.Auth
convention — tracked in-parent, not a nested repo). 3 dependency-split packages
(core / .Akka / .EntityFrameworkCore) + 3 test projects, .slnx, central PM.
Task 4: ZbHealthTags + MapZbHealth (/health/ready,/active,/healthz). 8/8 tests.
2026-06-01 06:35:39 -04:00
Joseph Doherty 07d5907258 docs(health): resolve spec/contract/gaps consistency (review fixes)
Applies canonical resolutions for eight settled decisions:
- GAPS: remove three stale "Decisions still open" bullets (#1 IActiveNodeGate placement, #2 GrpcChannel type, #3 OtOpcUaCompat named constant)
- Shared contract: AkkaClusterHealthCheck, ActiveNodeHealthCheck constructors take IServiceProvider (lazy ActorSystem, Degraded-when-not-ready)
- Shared contract: AkkaActiveNodeGate takes IServiceProvider; reads SelfMember+leader directly, null-guarded; does not proxy ActiveNodeHealthCheck
- Shared contract: DatabaseHealthCheckOptions.Probe renamed to ProbeQuery; consumer matrix updated
- Shared contract: settled AddZbHealthChecks open question removed (spec §5 is per-project AddHealthChecks)
- SPEC §2.2: OtOpcUaCompat Leaving/Exiting cell updated from — to Degraded + footnote; §2.3 startup-safety note added
- README: status line corrected from "built and tested" to "scaffolded … implementation is follow-on (task #7)"; IActiveNodeGate "left per-project" bullet removed
- OtOpcUa current-state: AddZbHealthChecks → AddHealthChecks().AddCheck<...>(); IClusterRoleInfo note reframed as accepted trade-off
- ScadaBridge current-state: IActiveNodeGate bullet rewritten — interface moves to ZB.MOM.WW.Health on adoption, InboundApiEndpointFilter references shared interface
2026-06-01 06:33:42 -04:00
Joseph Doherty 16540b3001 docs: design for audit normalization component + ZB.MOM.WW.Audit 2026-06-01 06:32:39 -04:00
Joseph Doherty 3d25ee5090 docs(health): current-state x3 + GAPS + README
Code-verified current-state docs for OtOpcUa (three-tier full), ScadaBridge
(two-tier, no /healthz), and MxAccessGateway (bare liveness only / no probes).
GAPS backlog with P1 for MxGateway and convergence items for Akka status policy,
DB probe technique, and response writer. README with per-project status table.
2026-06-01 06:23:53 -04:00
Joseph Doherty 1dc35a8c43 docs(health): spec + ZB.MOM.WW.Health shared contract
Authors components/health/spec/SPEC.md (normalized three-tier endpoint
convention, probe catalog, response-writer contract, migration notes) and
components/health/shared-contract/ZB.MOM.WW.Health.md (paper API for the
3-package library: core, Akka, EntityFrameworkCore).
2026-06-01 06:20:19 -04:00
Joseph Doherty c77df2a2cd docs: implementation plans for ZB.MOM.WW.Health + ZB.MOM.WW.Telemetry
Two TDD plans (one per library, per house precedent) derived from the approved
design, with co-located .tasks.json execution-persistence:

- Health: components/health docs + 3 dependency-split packages (11 tasks)
- Telemetry: components/observability docs + 2 packages (3 OTel signals +
  Serilog) + the MxGateway MEL->Serilog migration (12 tasks)

Each task carries classification / est-time / parallelizable metadata for the
executing-plans workflow.
2026-06-01 06:15:22 -04:00
Joseph Doherty 29b309c6c1 docs: design for health + observability normalization components
Adds the approved brainstorm design for the next two component-normalization
entries (Health #1, Observability #2 from upcoming.md):

- components/health/ -> ZB.MOM.WW.Health (3 dependency-split packages)
- components/observability/ -> ZB.MOM.WW.Telemetry (2 packages, 3 OTel signals
  + shared Serilog bootstrap)

Scope: normalization docs + build both libraries (.NET 10, tested, packed);
one sister-repo touch (MxGateway MEL->Serilog migration); no other app adoption.
Unifying hinge: one identity triple (service.name/site.id/node.role) feeds both
the OTel Resource and the Serilog enrichers.
2026-06-01 06:08:51 -04:00
Joseph Doherty b95c413c08 docs: add normalization backlog (upcoming.md)
Capture the next candidate components for the normalize → shared-library
treatment (Health, Telemetry, Audit model, gRPC contracts, Logging),
grounded in a cross-repo scan, so the backlog survives beyond this session.
2026-06-01 05:46:54 -04:00
Joseph Doherty 6185009554 Merge feat/zb-mom-ww-theme: ZB.MOM.WW.Theme shared UI kit (0.1.0) + ui-theme normalization component 2026-06-01 05:18:46 -04:00
Joseph Doherty 2485d86205 docs: register ui-theme component in indexes 2026-06-01 05:16:58 -04:00
Joseph Doherty 029ac0719b docs(ui-theme): current-state ×3 + GAPS adoption backlog 2026-06-01 05:15:38 -04:00
Joseph Doherty 95975d0754 docs(ui-theme): spec, design tokens, shared contract 2026-06-01 05:11:43 -04:00
Joseph Doherty 46ce627ea5 docs(theme): RCL README + verified pack
Full Release build (0 warnings, TreatWarningsAsErrors), 32/32 bUnit tests green.
Pack confirmed: staticwebassets/css/theme.css, staticwebassets/css/layout.css, and
the three IBM Plex woff2 fonts ship in ZB.MOM.WW.Theme.0.1.0.nupkg. README covers
the one-paragraph intro, 3-step Adopt guide, thin-MainLayout→ThemeShell delegation
example, component/enum reference table, static-asset paths, and build commands.
2026-06-01 05:05:26 -04:00
Joseph Doherty fe774f8ee4 fix(theme): correct sticky rail selector, harden bool attrs/tests, doc LoginCard security contract
- layout.css: fix @media sticky selector from #sidebar-collapse → #theme-rail (Fix 1)
- NavRailTests/CommonControlsTests: add TDD tests verifying Blazor omits false bool attrs (Fix 2)
- TechButton: rename Extra → AdditionalAttributes, move @attributes splat first (Fix 3)
- LoginCard: add security contract XML/comment docs on ReturnUrl and ChildContent (Fix 4)
- build/pack.sh, push.sh: fix comment from ZB.MOM.WW.Auth → ZB.MOM.WW.Theme (Fix 5)
2026-06-01 05:03:17 -04:00
Joseph Doherty cac2f659e4 feat(theme): ThemeHead stylesheet entry point 2026-06-01 04:56:26 -04:00
Joseph Doherty 40f6962d05 feat(theme): TechButton/TechCard/TechField 2026-06-01 04:56:06 -04:00
Joseph Doherty f7ec3fd732 feat(theme): LoginCard 2026-06-01 04:55:24 -04:00
Joseph Doherty b09de9b777 feat(theme): ThemeShell canonical side-rail
Add ThemeShell.razor (regular component, not LayoutComponentBase) with
Product, Accent, Logo, Nav, RailFooter, and ChildContent parameters.
Accent uses nullable AccentStyle so the style attribute is entirely
absent when null. Composes BrandBar inside .side-rail, wraps page in
<main class="page">. Add ThemeShellTests.cs (4 tests: product/nav/body,
accent sets css var, no-accent emits no style, RailFooter). All 18 tests
green, 0 build warnings.
2026-06-01 04:53:52 -04:00
Joseph Doherty 75e58085d1 refactor(theme): unify components into ZB.MOM.WW.Theme namespace
Add @namespace ZB.MOM.WW.Theme to each component .razor file so the
Razor compiler places all four components in the flat ZB.MOM.WW.Theme
namespace rather than ZB.MOM.WW.Theme.Components. Remove the now-
redundant global using ZB.MOM.WW.Theme.Components from both _Imports
files. Also add @namespace ZB.MOM.WW.Theme to the root _Imports.razor.
Consumers need only @using ZB.MOM.WW.Theme. All 14 tests green.
2026-06-01 04:53:12 -04:00
Joseph Doherty a74ad7008d feat(theme): NavRailItem + NavRailSection 2026-06-01 04:47:36 -04:00
Joseph Doherty 8e70718ca4 feat(theme): BrandBar 2026-06-01 04:46:58 -04:00
Joseph Doherty af8682c0f2 feat(theme): StatusPill widget 2026-06-01 04:46:24 -04:00
Joseph Doherty 6736415a32 feat(theme): vendor tokens, fonts, and side-rail layout CSS 2026-06-01 04:44:36 -04:00
Joseph Doherty 24fce87c96 feat(theme): scaffold ZB.MOM.WW.Theme RCL + test project 2026-06-01 04:41:48 -04:00
Joseph Doherty 5d1cae3fc6 docs: add ZB.MOM.WW.Theme implementation plan (13 tasks) 2026-06-01 04:39:06 -04:00
Joseph Doherty f9d570c323 docs: add UI-theme component design
Brainstormed design for normalizing UI theming across the 3 sister apps
into a single .NET 10 RCL (ZB.MOM.WW.Theme): canonical side-rail shell +
Technical-Light tokens/fonts as static assets + StatusPill/LoginCard/
TechButton-Card-Field, with per-app name/accent/logo. Mirrors the auth
component's path-to-shared-code treatment; app adoption tracked as
follow-on.
2026-06-01 04:29:58 -04:00
Joseph Doherty f624217af8 docs: add human-facing repo README
Complements CLAUDE.md (the Claude-Code index) with a human overview:
what's in here, the sister projects + data flow, the component-
normalization concept, and the ZB.MOM.WW.Auth package/consumer matrix
with build/test commands.
2026-06-01 04:12:43 -04:00
dohertj2 37e23cf9f2 Initial commit: scadaproj umbrella — sister-project index, auth component normalization (design + GAPS), and the built ZB.MOM.WW.Auth shared library (0.1.0, flattened in). 2026-06-01 03:59:23 -04:00