Files
ScadaBridge/docs/plans/2026-07-08-deferred-work-register.md
T
Joseph Doherty 22136d36d9 feat(testrun): route WaitForAttribute in the Test-Run sandbox (deferred #14)
Closes deferred-work register item #14 with full fidelity. The Central UI Test-Run
sandbox previously threw ScriptSandboxException for Attributes.WaitAsync/WaitForAsync;
now the value-equality forms route to the bound deployed instance over the same
cross-site path inbound Route.To().WaitForAttribute() uses.

- Commons: additive trailing RouteToWaitForAttributeRequest.RequireGoodQuality
  (default false; message-evolution safe) so quality-gated waits route too.
- SiteRuntime: DeploymentManagerActor's routed-wait handler now threads
  request.RequireGoodQuality into the InstanceActor WaitForAttributeRequest
  (previously hard-coded to default).
- CentralUI sandbox: ISandboxInstanceGateway.WaitForAttributeAsync +
  SandboxInstanceGateway impl (via CommunicationService.RouteToWaitForAttributeAsync);
  SandboxAttributeAccessor value-equality WaitAsync/WaitForAsync route through it
  (codec-encoded target, scope-resolved name). Predicate overloads stay unsupported
  (an in-process lambda can't be routed) and throw a clearer, dedicated message.
- Tests: sandbox accessor routing + predicate/unbound rejection (CentralUI);
  site-handler RequireGoodQuality threading (SiteRuntime). Register + the historical
  waitfor-deferred plan doc updated.

Full slnx build 0/0; CentralUI 59, SiteRuntime routed-wait 4, InboundAPI wait 32 green.

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
2026-07-10 09:29:38 -04:00

6.6 KiB
Raw Blame History

Deferred-Work Register (established 2026-07-08, from architecture review 08)

Single tracked list of consciously-deferred work. Rules: every deferral gets a row (rationale + revisit trigger); fix-now items reference the archreview plan that owns them and are removed from this table when that plan's task lands.

Fix-now (owned by archreview plans)

# Item Owner
1 Transport: Area membership doesn't travel in bundles (EntitySerializer.cs:251,518) PLAN-05
2 CLI.Tests not in slnx PLAN-08 Task 1
3 AuditLog reconciliation dials site NodeA only (SiteEnumerator.cs:32,64) PLAN-04
4 Options validation missing on ~12 components PLAN-08 Tasks 25
5 SmsConfiguration.MaxRetryCount stored but not honored PLAN-06
6 Role-check case-sensitivity asymmetry (ManagementActor.cs:1910) PLAN-07
23 Vestigial site-side notification-list surface PLAN-08 Task 6

Deferred (with rationale + revisit trigger)

# Item Where noted Rationale for deferral Revisit trigger
8 Hash-chain tamper evidence (T1); CLI verify-chain is a no-op stub audit-log roadmap :12 v1.x by locked decision; append-only DB roles are the control Compliance requirement for cryptographic tamper evidence
9 Parquet audit archival (T2); endpoint returns 501 AuditEndpoints.cs:204 v1.x; 501 + CLI messaging are honest AuditLog partition volume nears retention ceiling
10 Aggregated live alarm stream for Alarm Summary m7 design :252 Snapshot fan-out acceptable at current instance counts Alarm Summary latency complaints or >~50 instances/site
11 Central-persisted OPC UA cert-trust audit m7 follow-ups Broadcast-to-both-nodes covers HA Governance/audit requirement for trust decisions
12 Native-alarm-source-override CSV import — Central UI InstanceConfigure upload affordance only (CLI + Management API + parser shipped 2026-07-10, see Resolved) m7 follow-ups CLI/API path closes the operator parity gap; the Blazor upload button is polish First request to bulk-import native sources from the UI rather than the CLI
17 Unified notifications+site-calls outbox page stillpending :118 Explicit M9 decision to keep two pages Operator confusion reports
18 Folder drag-drop same, [PERM] Permanently closed; menu reorder shipped — (closed)
19 Bundle signing / cluster-to-cluster pull / differential bundles transport-design :402 v1 manifest hash + AES-GCM held sufficient Non-repudiation requirement across orgs
22 KPI history hourly rollups Component-KpiHistory.md YAGNI; 90-day retention bounds table KpiSample query latency on dashboards

Resolved (verified against the code 2026-07-10)

Rows removed from the Deferred table above once confirmed shipped. Kept here for traceability.

# Item Resolution
7 SecuredWrite audit rows leave SourceNode NULL Resolved (PLAN-07): ManagementActor.EmitSecuredWriteAuditAsync routes through ICentralAuditWriter, which stamps SourceNode (central-a/central-b) from INodeIdentityProvider.
12 (CLI/API) Native-alarm-source-override CSV import Shipped 2026-07-10: shared CsvLineSplitter, NativeAlarmSourceOverrideCsvParser, bulk all-or-nothing SetInstanceNativeAlarmSourceOverridesCommand + ManagementActor handler (Deployer-gated), CLI instance native-alarm-source import --file, parser/CLI/handler tests. UI upload affordance still pending — see row 12 above.
13 WaitForAttribute quality-gated ("Good"-only) mode Already implemented (Commons WaitForAttribute.RequireGoodQuality, enforced in InstanceActor, threaded through ScriptRuntimeContext, tested in InstanceActorWaitForAttributeTests). Stale "planned enhancement" doc line corrected 2026-07-10.
14 WaitForAttribute in Test-Run sandbox Shipped 2026-07-10 (full fidelity): sandbox Attributes.WaitAsync/WaitForAsync (value-equality) route to the bound instance via ISandboxInstanceGateway.WaitForAttributeAsync → the existing CommunicationService.RouteToWaitForAttributeAsync cross-site route. Additive RouteToWaitForAttributeRequest.RequireGoodQuality (honored by the site handler) makes quality-gated waits route too. Predicate-form waits stay unsupported (an in-process lambda can't be routed) and throw a labelled ScriptSandboxException. Tests: sandbox accessor routing (CentralUI), site-handler quality-flag threading (SiteRuntime).
15 BrowseNext final-page signal not surfaced Already surfaced (M7 browse work): RealOpcUaClient sets Truncated=false/ContinuationToken=null on the last page; BrowseNodeResult carries both; TreeRow.razor renders "Load more" only when a continuation token remains — no wasted BrowseNext.
16 StubOpcUaClient throws on browse Already resolved: StubOpcUaClient supports browse + address-space search, covered by StubOpcUaClientBrowseTests/StubOpcUaClientSearchTests.
20 Deployment EXPIRED-row purge Already resolved (PLAN-04): PendingDeploymentPurgeActor central singleton (spawned in AkkaHostedService) ticks IDeploymentManagerRepository.PurgeExpiredPendingDeploymentsAsync every CommunicationOptions.PendingDeploymentPurgeInterval (default 1h), options-validated, tested.
21 SiteAuditBacklogReporter threshold consolidation Shipped 2026-07-10: SqliteAuditWriterOptions.BacklogPollIntervalSeconds (default 30) now drives the reporter's poll cadence; explicit ctor override still wins (tests), non-positive falls back to the 30 s default. Cadence tests added; stale "hard-code / follow-up" class-doc corrected.

New deferrals from review 08 (this plan)

Item Rationale Revisit trigger
Communication → HealthMonitoring layering (ICentralHealthAggregator consumed by CentralCommunicationActor.cs:351) Moving the interface + SiteHealthState to Commons ripples across 5 projects for a cosmetic inversion Next breaking change to ICentralHealthAggregator
docs/components reference docs for ScriptAnalysis, KpiHistory, DelmiaNotifier Reference docs are substantial (StyleGuide-conformant); README claim scoped instead (PLAN-08 Task 10) Next doc-writing session touching those components
Test-coverage backfill: SiteCallAudit.Tests (31 tests/1.6k LOC), DeploymentManager.Tests No defect identified; coverage partly lives in ManagementService/Host/Integration suites First regression escaping either component
Failover-timing + broader perf envelope (S&F drain rate, per-subscriber backpressure) Needs PLAN-01 two-node rig; placeholder harness shipped (PLAN-08 Task 8) PLAN-01 rig landing