Replaces the 2026-09-11 remote-exec hold: WinRM exec is allowed only for the on-box steps of a
user-requested deploy; ad-hoc diagnostics/version checks use SMB, HTTP or SQL. SMB file copies and
direct SQL logins remain always allowed. Scope rules live in the winrm skill's Scope section.
CLAUDE.md: ScadaBridge row records main @ 17864d1a (records only, code tip
2b9a7c3c) deployed on vd03 and the vq03/vq04 pair; Theme/Auth/LocalDb rows
lose their "not yet deployed" caveats (QA pair now runs LocalDb replication,
connected); tier note gains the deployed-state line and the winrm access path.
deployment.md: §2.1 access rows replaced by the winrm skill (WinRM 5985 +
SMB 445; servecli/psbridge retired), §7.1 port map gains 5985/445 and marks
6150 retired, live-state table updated (OtOpcUa active flipped to node-a),
new "Deployed builds on QA" paragraph, §9 deployed-state summary.
Claude-Session: https://claude.ai/code/session_01RgthVLVU5CJ8SUuEwruTkt
Row in the sister-project table, a BTDB-edges subsection (Galaxy write contract, ScadaBridge inbound-API SAPID lookup on db-connection BTDB, Historian CLR/INSQL co-location), break-surface note, Windows-only build commands, and the DARS bullet now points at the unversioned WW_ARCH/BatchTracker_DB fork. Full schema/contract notes and the 2026-09-03 gap analysis live in .claude/skills/sister-project-history/btdb.md.
Claude-Session: https://claude.ai/code/session_01Wzg6NUCWHipSexLs2cgRFv
Baselining one table used to set a single per-DATABASE needs_snapshot bit, and a
snapshot streams every registered table in full — so opting one table into
replication late re-sent all of them, in both directions at once on a pair
enabling replication late. On a database holding a high-volume table (an event
log at its retention cap) that is the largest transfer this library performs.
0.2.1 documented the cost and deferred the fix as needing an on-disk change.
Schema v3 adds __localdb_snapshot_state (table_name PK, needs_snapshot), created
by the shared DDL with IF NOT EXISTS so an older file gains it on open; the v2->v3
transition is a version stamp only. RegisterReplicated(..., baselineExistingRows:
true) now flags that table alone. The database-wide flag survives unchanged for
the paths that genuinely reach every table — a cap prune or an impossible peer ack
loses delta continuity for the oplog as a whole. DeregisterReplicated drops a
table's pending flag with its ledger rows, since nothing would ever stream (and so
clear) it afterwards.
Wire compatibility is additive and negotiated by CAPABILITY, not version:
lib_schema_version stays 1 because ValidateHandshake compares it fail-closed for
equality, so bumping it would stop 0.1.x/0.2.x pairs syncing outright. Handshake
gains supports_partial_snapshot (field 5) and SnapshotBegin gains a tables scope
(field 2) where EMPTY means all tables — precisely what a pre-0.3.0 sender emits
and what a pre-0.3.0 receiver assumes. A peer that does not advertise the
capability is served a full snapshot: a scoped one would make it advance
last_applied_remote_seq to the snapshot's as-of and silently discard every delta
below it for the tables left out.
For the same reason a partial snapshot moves no watermark on either side. The
receiver keeps last_applied_remote_seq (carrying only the HLC across, which is
MAX-guarded), and the sender keeps _sentThruSeq, so the deltas the snapshot
overlaps are still pumped and merged by LWW.
Crash safety: snapshot debt now clears on the receiver's new SnapshotAck rather
than on enqueue, so an ungraceful exit part-way through re-streams the same scope
on reconnect. The ack rides the unbounded CONTROL lane like DeltaAck, so it
composes with 0.2.1's bounded 64-message inbox and its out-of-handshake snapshot.
Against a pre-0.3.0 peer the 0.2.x clear-on-enqueue behaviour is kept — there is
no ack to wait for — with the handshake's horizon gap check as the net.
Tests 199/199 (was 188): single-table baseline streams only that table, mixed-
version interop (peer without the capability gets a full snapshot), debt standing
until SnapshotAck, partial snapshot not advancing the receiver's watermark, no
SnapshotAck emitted to an old peer, end-to-end over two real databases, plus v2->v3
upgrade and per-table flag isolation.
README, ILocalDb remarks (which named this as the follow-up) and the umbrella
CLAUDE.md index updated.
The umbrella LocalDb row and the pack/test quick-reference now name 0.2.1 (188 tests,
3 nupkgs on the feed). Records both findings, the snapshot-out-of-handshake change that
bounding the inbox required, and the deferred per-table needs_snapshot. Consumer pins are
unchanged: ScadaBridge still pins 0.2.0, OtOpcUa still pins 0.1.3.
deployment.md:
- §1/§2.1: add wonder-app-vq03, wonder-app-vq04 and wonder-sql-vq03 with IPs and
per-host roles; new §7.1 QA port map + live active/standby state.
- QA is a real 2-node HA pair (ScadaBridge central+site pairs, OtOpcUa pair) where
DEV is a single all-in-one box, so it is the only environment here that exercises
failover and leader election. MxGateway/HistorianGateway/Overview run on vq03 only.
- Every QA fact is marked scan (port probe) or dash (read off the QA Overview
dashboard's live polling). No QA config file was read; connection strings and
service names stay unverified.
- Correct the tier: vd03 is DEV, not production (vd=dev, vq=qa, per
mes-delmia-integration-api.md §1.1). Its ASPNETCORE_ENVIRONMENT really is
"Production" -- a .NET overlay name, orthogonal to the tier, and the likely source
of the original error. No production box has been identified.
- Record that QA requires Basic auth on /management where DEV does not, so DEV-only
procedures relying on unauthenticated management calls will not work on QA.
- Record that inbound API keys never cross environments (per-stack peppered-HMAC,
excluded from config bundles) plus the 401-vs-400 probe, with the caveat that auth
runs before route resolution so a 401 needs a positive control.
- Withdraw the SSH-on-2222 claim made earlier in this same pass: all three wonder
boxes accept TCP on 2222 and send no SSH banner, so servecli is not serving SSH and
no shell access was available. Port scan cannot establish a service; banner grab can.
CLAUDE.md:
- Overview: record the second instance on wonder-app-vq03:5320, and that its real-FQDN
registry is correct rather than a divergence -- the 127.0.0.1 rule is specific to
vd03 co-locating every instance on one host.
- Add the DEV-vs-prod note pointing at deployment.md §2.1/§7.1.
CLAUDE.md: feed now carries 0.2.1; record the referral defect and that every
app is still exposed until it bumps off 0.1.5 (a functional fix, not
housekeeping), plus the new tools/LdapProbe.
ldap_setup.md: findings from probing the live NAM directory --
- LDAPS 636, StartTLS 389 and plain 389 all connect on both DCs. The only TLS
chain error is UntrustedRoot, so installing zimmer-rootca is sufficient; the
RSA 1024-bit key is rejected only by OpenSSL at SECLEVEL=2, i.e. Debian .NET
containers, not by macOS or Windows hosts.
- The UG_WW_* Wonderware group convention, 39 groups enumerated directory-wide.
This partly overturns this doc's earlier "no group->role convention exists"
claim: that was true of Ignition, which was the only source audited, and
false of the domain. Three shapes with a consistent role suffix (ADMIN, RO,
OPERATOR, ENGINEER, SUPERVISOR, TESTER) across environment and site axes.
- A proposed mapping onto CANONICAL-ROLES, with the three gaps left open
rather than guessed: SUPERVISOR/TESTER have no canonical equivalent, nothing
maps to Deployer, and the DEV/QA/PROD axis is orthogonal to role so it must
ride in the per-project scope payload or the role set triples.
- The referral defect and its fix.
This repo hosts one application besides its shared libraries, and the index did
not mention it at all. Adds what it is, that its registry ships empty by design,
and the two constraints that bit during the first real deployment: publish
self-contained (wonder has no .NET 10 runtime), and do not put co-located
instances on a shared host name, because leader-to-instance resolution matches on
host only and the first match wins the chip for every group.