Resolve all 46 low-severity architecture review findings

This commit is contained in:
Joseph Doherty
2026-09-09 22:56:36 -04:00
parent fef3e7675f
commit 9ee402bbcd
139 changed files with 2621 additions and 1082 deletions
@@ -230,6 +230,19 @@ The two-person authorization workflow for writes through the MxAccess Gateway. B
- **VerifyEndpointCommand**: Ask a site to probe an OPC UA endpoint (temporary client, short timeout) and report success / typed failure / a captured-but-untrusted server cert. Read-only — never trusts. Actor-dispatched, `SiteIdentifier`-required + site-scope, relayed via `CommunicationService.VerifyEndpointAsync` (arch-review C4). (`Design` role — runs inside the Admin-gated connection editor.)
- **TrustServerCertCommand** / **RemoveServerCertCommand** / **ListServerCertsCommand**: Manage the site's OPC UA trusted-peer PKI store; Trust/Remove broadcast to **both** site nodes (see Component-SiteRuntime.md). Actor-dispatched and `Admin`-gated at the actor (arch-review C4) — each handler requires the command's `SiteIdentifier`, enforces site-scope, then relays via `CommunicationService.TrustServerCertAsync` / `RemoveServerCertAsync` / `ListServerCertsAsync`; the site-side reconcile across both nodes is owned by the site `CertStoreActor`. (`Admin` role.)
### Flow Debugger
All four commands return `FlowDebugRunResult`: the chain root execution ID, completion/error metadata, audit events, timestamps, and independent event/log truncation flags.
| Command | Behaviour | Required role |
|---|---|---|
| `FlowDebugRunMethodCommand` | Validates an inbound API method's parameters and runs it with tracing; routed calls enforce the caller's site scope. | Deployer |
| `FlowDebugRunValueChangeCommand` | Writes an instance attribute through the real site path and polls for the triggered execution tree. | Deployer |
| `FlowDebugRunScriptCommand` | Resolves the effective script; writes its trigger attribute for write-trigger kinds, otherwise invokes it directly with validated parameters. | Deployer |
| `FlowDebugReplayCommand` | Reads the stored execution tree for any execution ID, enforcing caller scope and retaining the repository's chain anchor. | Any of Deployer, Administrator, Viewer |
Live commands require the active central node and return `STANDBY_NODE` elsewhere. They perform real script/device operations and write operator-attributed audit roots. One cancellation budget starts at runner entry, covers lookups, execution/write, audit and trace pulls, and reserves five seconds below `LongRunningCommandTimeout` for the reply. Configuration must exceed that grace. Write-trigger waits are clamped to 1–295 seconds and the remaining total budget. Polling drains all `(OccurredAtUtc, EventId)` keyset pages in execution-ID batches of at most 64. Each subsequent poll intentionally rescans those batches: closing rows are inserted at completion but stamped with their start time, so a persistent timestamp cursor would miss them. The root is a fresh execution GUID; scans use no timestamp lower bound and do not require central/site clock agreement. This removes fixed-page starvation but deliberately retransfers known rows. Site reads use partial valid-JSON execution/parent-expression indexes; an indexed union of keys deduplicates both matches and limits the page before loading payloads. Malformed legacy details are excluded from trace matching without preventing index initialization. Discovery retains deduplicated rows for the bounded command duration, so working memory grows with the traversed tree; only the returned reply has a fixed collector cap. Inline results use `FlowTraceCollector` count/byte caps and expose truncation. Replay also has repository count/UTF-8 bounds; it does not execute scripts or write to devices.
## Authorization
Every incoming message carries the authenticated user's identity and roles. The ManagementActor enforces the same role-based authorization rules as the Central UI: