Captures the 2026-06-05 coverage audit's gaps and the approved approach for
closing them: ephemeral CLI-provisioned fixtures with outcome-tolerant asserts
for the mutating suites (deploy lifecycle, retry/discard, transport import),
UI CRUD round-trips, nav render hardening, a Health KPI load test, and a
standardized skip-and-log policy. Next: writing-plans turns this into tasks.
Brainstormed design: generate 25 StyleGuide-conformant developer-reference
docs derived from src/ code (pilot AuditLog, then parallel fan-out, then
accuracy/conformance verification). Complements the requirements specs;
leaves src/, XML docs, and specs untouched.
Gitea renders mermaid inline, so the flow/state/hierarchy/DAG diagrams
move to text-in-markdown: auto-layout (removes the manual overlap-prone
draw.io step), diffable source, no committed binaries, and a dark-text
theme so labels stay legible. Keep draw.io PNGs only for the two complex
bespoke diagrams (logical architecture, env2 topology) where pixel
control still wins. All 24 mermaid blocks validated by rendering.
Replace ASCII-art diagrams across the README and docs/ with editable
.drawio sources plus exported PNGs, so the diagrams render clearly in
rendered markdown and can be maintained/regenerated instead of being
hand-edited as fragile text art. Non-diagram blocks (code, folder
trees, UI wireframes) were left as text.
Renames the 13 SCADALINK_* runtime env vars → SCADABRIDGE_*, the ScadaLink__
.NET config keys → ScadaBridge__, the stale ScadaLink.Host.exe assembly name
→ ZB.MOM.WW.ScadaBridge.Host.exe, the scadalink_app SQL login → scadabridge_app,
and residual identifiers/comments/docs. Migration records (prior rename
tooling/design, DB-rename helper, this scrub script) carved out.
Adds tools/scrub-scadalink-refs.sh.
The native alarms feature merged with 7 component docs updated, but the
spec layer drifted: HighLevelReqs, Commons, and ManagementService had no
native-alarm coverage and the README table flagged it on only one row.
Add HighLevelReqs §3.4.2 (+ validation), document the Commons
types/entities/messages and the 7 ManagementService commands, sync the
README rows + link the TreeView sub-component, fix 2 broken plan links,
and drop the one-off native-alarms RESUME scratchpad.
Read-only mirror of native alarm sources into a unified A&C-style state
model (severity + active/acked/shelved/suppressed). Instance-bound source
discovery, site-only SQLite state with live central query (no central
tables), DebugView enrichment. OPC UA A&C events + ConditionRefresh and
MxGateway session-less StreamAlarms via a new IAlarmSubscribableConnection
seam routed connection-level by source reference; new NativeAlarmActor peer
to computed AlarmActor.
Add design doc for a second data-connection protocol, MxGateway, alongside
the OPC UA client. New IDataConnection adapter behind the existing
DataConnectionFactory extension point; tag pipe (read/subscribe/write) plus
Galaxy hierarchy browse, optional 2nd endpoint for failover. Generalizes the
OPC-UA-named browse plumbing to protocol-agnostic browse via
IBrowsableDataConnection. No entity/schema changes.
Five phases, PR-shippable per phase: schema/contracts, DCL browse capability,
flattening uses override, Central UI popup + integration, docs. Per-task
classification, time estimates, and parallelism declared.
Per-instance address override + live ClusterClient-based browse via a new
IBrowsableDataConnection capability on RealOpcUaClient. Lazy-loaded tree
with manual-paste fallback; offline-safe.
Decisions: full prefix in csproj names + namespaces, full runtime
artifact rename (containers/network/DBs), staged commits on main,
in-place MS SQL DB rename, wipe site SQLite on cutover.
11-task plan (T0-T10) covering the sibling docker-env2/ directory:
SQL setup script + mount, Traefik config, central/site appsettings,
docker-compose, lifecycle scripts, .gitignore, READMEs and cross-refs,
verification checklist, and a manual smoke test. No application code
changes -- pure deploy tooling. Most tasks (T0-T9) are independent
and parallel-ready; T5 is gated on T0 + T4; T10 gates on all of T0-T9.
Brainstorming output for a sibling docker-env2/ tree that brings up a
minimal second cluster (2 central + 1 site x 2 nodes + Traefik) on the
same machine alongside the primary docker/ stack. Shares the existing
scadalink-net network and scadalink-mssql container but uses separate
logical databases (ScadaLinkConfig2 / ScadaLinkMachineData2) so the
Transport (#24) feature can be exercised end-to-end with real
cross-environment exports and imports.
File-based, encrypted bundle export/import via the Central UI for
promoting templates, system artifacts, and central-only configuration
across environments. Site-scoped artifacts excluded. Per-artifact
conflict resolution; config-only import (user redeploys via existing
Deployments page). Per-entity audit rows correlated by BundleImportId.
Tidies flagged by code review on the T6/T7/T8 migration bundle:
- Add `.IsUnicode(false)` to the three SourceNode EF property mappings to
match every other ASCII varchar column on the same entities. Physical
column was already `varchar(64)` because `HasColumnType` wins, but the EF
model metadata flag was inconsistent.
- Add `unicode: false` to the three AddColumn<string> calls in the migrations
+ their Designer snapshots so the historical snapshots match the model.
- Update the model snapshot to carry IsUnicode(false) on each SourceNode entry.
- Document the SELECT-list invariant on SiteCallAuditRepository.QueryAsync:
EF Core's FromSqlInterpolated requires every entity-tracked column in the
result set, so future SiteCall columns must extend the list too.
- Amend plan Task 6 Step 2 to document the partition-aligned raw-SQL index
recipe and the staging-table sync requirement.
- Adds SourceNode varchar(64) NULL to AuditLog, Notifications, and SiteCalls
tables with role-name semantics: node-a/node-b for site rows (qualified by
SourceSiteId), central-a/central-b for central direct-write rows.
- New IX_AuditLog_Node_Occurred (SourceNode, OccurredAtUtc) index.
- Reframes CLAUDE.md from documentation-only to implementation project.
- Adds docs/plans/2026-05-23-audit-source-node.md + tasks.json companion.
The design doc claimed (in two places) that InboundAuthFailure rows
were excluded from the inbound full-body carve-out — but the actual
implementation gates the carve-out on Channel == ApiInbound, NOT Kind.
Every audit row the InboundAPI middleware emits (whether
Kind = InboundRequest or Kind = InboundAuthFailure) carries
Channel = ApiInbound, so both Kinds receive the inbound ceiling. That
is the intended behaviour: an auth-failure row's request body is
exactly the body the operator wants to see in full when investigating
a rejected request.
Update both occurrences (Decision block + Not in Scope block) to say
the carve-out applies to all Channel = ApiInbound rows regardless of
Kind. Pure documentation change — no code drift.