Files
scadaproj/components
Joseph Doherty 544a6ddb77 Fix all baseline code-review findings across the six shared libraries
Resolves the 35 findings from the 2026-06-01 baseline (commit 26ba1c7),
test-first for every behavioral change. +51 tests (331 -> 382 passing, 0 failed).

- Telemetry-001 (HIGH): RedactionEnricher now honours property removal, so a
  redactor that drops a key actually scrubs the secret from the event.
- Auth: LDAP validator ValidateOnStart; API-key verify no longer fails on a
  best-effort MarkUsed write or a corrupt scopes column (fail-closed); LDAP cert
  validation hook; KeyPrefix persistence aligned; README algorithm corrected.
- Health: Akka checks return Degraded (not throw) when the cluster isn't up yet;
  GrpcDependencyHealthCheck catch-all; null 'description' rendered; composite
  endpoint builder; XML docs shipped.
- Audit: CompositeAuditWriter no longer re-throws OperationCanceledException;
  TruncatingAuditRedactor over-redact scrubs Target + safe negative max; options
  record; XML docs shipped.
- Configuration: TryAddEnumerable idempotent registration; consistent port
  quoting; strict invariant port parsing; XML docs + README packaged.
- Theme: mobile toggle is now CSS-only (no Bootstrap JS); token/CSS hygiene;
  XML docs on the public parameter surface.

Shared-contract/spec docs updated where the code was the source of truth
(observability service.instance.id, MapZbMetrics, redactor reach). All changes
additive/back-compatible at v0.1.0. code-reviews bookkeeping follows separately.
2026-06-01 11:22:14 -04:00
..

Component normalization

This tree normalizes how cross-cutting components work across the sister projects indexed in ../CLAUDE.md (currently OtOpcUa, MxAccessGateway, ScadaBridge). The sister repos are deliberately decoupled — separate processes coupled only over wire protocols — so the same concern (auth, logging, config, health, …) tends to get re-implemented three times and drift apart. This folder is where we write down the one target for each such component, record where each project stands today (verified against real code), and track the gaps that close the distance between them.

The goal is convergence toward shared, versioned contracts/libraries — see each component's shared-contract/. Nothing here changes project code directly; these are specs and analyses that drive changes made in the individual repos.

Component registry

Component Status Applies to Goal Folder
Auth (login / identity / authz) Draft OtOpcUa, MxAccessGateway, ScadaBridge Path to shared code (ZB.MOM.WW.Auth) auth/
UI Theme (layout / tokens / components) Draft OtOpcUa, MxAccessGateway, ScadaBridge Path to shared code (ZB.MOM.WW.Theme) ui-theme/
Health (readiness / liveness / active-node) Draft OtOpcUa, MxAccessGateway, ScadaBridge Shared ZB.MOM.WW.Health lib (3 packages) health/
Observability (metrics / traces / logs) Draft OtOpcUa, MxAccessGateway, ScadaBridge Shared ZB.MOM.WW.Telemetry lib (2 packages) observability/
Config + validation (options / startup validation) Draft OtOpcUa, MxAccessGateway, ScadaBridge Shared ZB.MOM.WW.Configuration lib (1 package) configuration/
Audit (event model + writer seam) Draft OtOpcUa, MxAccessGateway, ScadaBridge Path to shared code (ZB.MOM.WW.Audit) audit/

Add a row when you start normalizing a new component. Status: DraftReviewedAdoptingConverged.

Folder convention

Every normalized component is one subfolder of components/ with this layout:

<component>/
  README.md                     # overview + per-project status table (links into the docs below)
  spec/
    SPEC.md                     # the ONE normalized target for this component
  shared-contract/              # only when the goal is shared code
    <Package>.md                # proposed shared-library API: packages, interfaces, options, records
  current-state/
    <project>/                  # one subfolder per project the component applies to
      CURRENT-STATE.md          # how it works in THAT project today (code-verified) + adoption plan
  GAPS.md                       # divergences of each project vs SPEC.md + the extraction/adoption backlog
  • spec/SPEC.md is authoritative: the single design every project should converge on.
  • shared-contract/ exists only when the component's goal is shared code (vs docs-only convergence). It is the proposed public API of the library to extract — a contract on paper, not a created package.
  • current-state/<project>/ is descriptive, not aspirational. It must match the project's real code, with file:line references. Each ends in an Adoption plan: what that project deletes/replaces to reach the spec, and what stays bespoke.
  • GAPS.md is the working backlog: it turns the delta between every current-state and the spec into concrete, prioritized items.

Workflow to normalize a component

  1. Map current state from code. For each applicable project, read the actual implementation (not just its CLAUDE.md) and write current-state/<project>/CURRENT-STATE.md with file:line refs. Fan out one reader per project — they're independent.
  2. Write the target. Synthesize the common ground and the divergences into spec/SPEC.md — the one design. Call out explicitly what is normalized vs. what stays per-project (domain differences that should not be forced together).
  3. Propose the contract (if shared-code goal). Turn the spec's normalized seams into a concrete library API in shared-contract/. Keep the surface minimal — extract only what is genuinely common; leave domain-specific logic in the projects.
  4. Log gaps + adoption. Fill GAPS.md with per-project divergences and an adoption/extraction backlog (priority / effort / risk). Add the per-project "what to delete/replace" to each current-state doc.
  5. Register. Add/maintain the component's row in the registry table above.

Maintenance rules

  • current-state/<project>/CURRENT-STATE.md must stay code-verified. When a project's auth (or whichever component) changes materially, update its current-state doc and re-check GAPS.md.
  • The spec/ is changed deliberately, with the same "update the doc and the consequences" discipline the sister repos use — moving the target re-opens gaps.
  • Keep cross-references accurate: README.md status tables link to the docs; don't let them rot.