All 3 apps adopted on branch feat/adopt-zb-telemetry (behaviour-preserving). Records the per-repo result + accepted scope deviations (ScadaBridge keeps LoggerConfigurationFactory + TraceContextEnricher instead of AddZbSerilog; MxGateway keeps GatewayLogScope, exposes redaction via ILogRedactor seam) and deferred follow-ons (#6 ms->s, #7 meter rename, #9 app instruments, OTLP, and the new ScadaBridge Site-node HTTP/1.1 metrics-listener item). Corrects the prior false 'MxGateway logging adopted on its own branch' claim — that migration actually landed in this pass.
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:
Draft→Reviewed→Adopting→Converged.
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.mdis 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, withfile:linereferences. Each ends in an Adoption plan: what that project deletes/replaces to reach the spec, and what stays bespoke.GAPS.mdis the working backlog: it turns the delta between everycurrent-stateand thespecinto concrete, prioritized items.
Workflow to normalize a component
- Map current state from code. For each applicable project, read the actual implementation
(not just its
CLAUDE.md) and writecurrent-state/<project>/CURRENT-STATE.mdwithfile:linerefs. Fan out one reader per project — they're independent. - 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). - 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. - Log gaps + adoption. Fill
GAPS.mdwith per-project divergences and an adoption/extraction backlog (priority / effort / risk). Add the per-project "what to delete/replace" to eachcurrent-statedoc. - Register. Add/maintain the component's row in the registry table above.
Maintenance rules
current-state/<project>/CURRENT-STATE.mdmust stay code-verified. When a project's auth (or whichever component) changes materially, update its current-state doc and re-checkGAPS.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.mdstatus tables link to the docs; don't let them rot.