Commit Graph

15 Commits

Author SHA1 Message Date
Joseph Doherty 298a9af59e fix(deploy): classify AskTimeoutException as a deploy timeout
Akka.Actor.AskTimeoutException does not derive from System.TimeoutException,
so the isTimeout check in DeployInstanceAsync's catch block missed it and
routed it to the generic "Deployment error:" branch. This broke the
DeploymentManager-006 reconciliation query (query-before-redeploy), which
keys off the "Communication failure:" prefix to detect a prior timeout-induced
failure. Add AskTimeoutException to the pattern; add a covering regression test.
2026-06-26 13:15:19 -04:00
Joseph Doherty 10f752df02 feat(deploy): stage pending config + send RefreshDeploymentCommand (notify-and-fetch) 2026-06-26 13:06:07 -04:00
Joseph Doherty cdd65beb6c feat(cli+templateengine+deploymanager): resolve follow-ups #4/#5/#6/#8 — CLI ergonomics + structured deploy validation error
Closes the four remaining items in the 2026-06-24 template-inheritance/CLI
follow-up tracker.

#4 — CLI `instance set-bindings` can now set DataSourceReferenceOverride.
  `--bindings` accepts an optional 3rd element per entry:
  [attributeName, dataConnectionId, dataSourceReferenceOverride]. A string
  sets the override; a JSON null or an omitted 3rd element leaves it unset
  (template default). TryParseBindings accepts 2- or 3-element entries and
  rejects a non-string/non-null 3rd element or 4+ elements with a clean
  error. Previously the CLI sent the override as null and silently wiped any
  existing one (only a raw POST /management could set it).

#5 — `template update` is partial, not full-replace (fixed server-side so all
  clients benefit). UpdateTemplateAsync now uses leave-unchanged semantics:
  a null description keeps the stored value (pass "" to clear); a null
  parentTemplateId keeps the existing parent. Parent stays immutable — a
  non-null differing value is still rejected — but omitting --parent-id is
  now a no-op instead of failing every derived-template update.

#6 — compact `template list`/`get` table output + `--detail`. Table output is
  now id/name/description/parent/derived + member counts (#attrs/#alarms/
  #scripts/#comps/#nativeAlarms) via TemplateTableProjection, fed through a
  new optional tableProjector seam on CommandHelpers. `--detail` restores the
  full dump. JSON output is left untouched (always full) so machine consumers
  are unaffected — the projector only runs on the table path.

#8 — structured deploy-time validation error. New ValidationResult.SummarizeErrors()
  (Commons) returns a grouped, capped summary: leading total count, one line
  per ValidationCategory, and a per-module rollup (canonical name up to its
  last dot) with counts + "... and N more module(s)" caps. DeploymentService
  uses it for the "Pre-deployment validation failed" message and logs the full
  per-entry list via LogWarning. Replaces the flat semicolon-joined dump that
  became a wall of text for instances with 50-194 unbound attributes.

Tests: +8 Commons (SummarizeErrors), +8 CLI (4 binding 3-element / 4 table
projection), +2 net TemplateEngine (partial-update). Affected suites green:
Commons 587, CLI 341, TemplateEngine 447, DeploymentManager 101,
ManagementService 230, CentralUI 866; full solution builds 0/0.

Docs: Component-DeploymentManager.md "Validation Error Reporting"; CLI README
(set-bindings 3-element form, template update leave-unchanged, list/get
--detail); UpdateTemplateCommand doc; known-issues tracker #4/#5/#6/#8 resolved
(all 8 items now closed).
2026-06-24 18:27:42 -04:00
Joseph Doherty fd618cf1dc fix(review): full code-review remediation — 5 High + Medium/Low across 16 modules
Remediation from the full per-module code review at 4307c381 (findings recorded
separately in code-reviews/).

Highs fixed:
- DeploymentManager-025/SiteRuntime-031: stop broadcasting notification lists + SMTP
  configs (incl. credentials) to sites; site purges already-persisted rows on apply
  (enforces the central-only delivery design; clears plaintext SMTP creds at rest).
- DataConnectionLayer-023: guard the native-alarm subscribe path against the
  mid-flight-unsubscribe adapter-feed leak (mirrors the DCL-021 tag-path fix).
- SiteEventLogging-024: normalize From/To query bounds to UTC (the -016 fix the
  audit trail claimed but never committed).
- KpiHistory-001: add an in-flight guard to the recorder sample tick.
- ScriptAnalysis-001: harden the trust analyzer's TPA-absent fallback (resolve
  forbidden anchors in the minimal reference set; warn on degraded mode) — anchors
  added to validation references only, never the compile gate.
(InboundAPI-026 left to the feat/ipsen-movein effort per owner decision.)

Medium/Low: DM-026 deterministic deploy-status tiebreaker; SR-027/028/029/030
native-alarm leak/phantom-active/delete-during-redeploy fixes; AL-013/014/016;
TE-024 (folder-mutation audit rows now persisted)/025; SF-025 gauge-provider
clear-on-stop; ESG-025/026; SEC-023/024/025; SCA-007/008/009; plus doc/test
accuracy COM-023/024, HOST-025/026, HM-024/025, NS-027/028.

Full-solution build 0 warnings; ~3560 tests across 18 touched suites green.
2026-06-20 17:55:12 -04:00
Joseph Doherty 095361b73f fix(sms): repair S1 build breaks — null-filter EmailAddress projections + SiteNotificationRepository SMS stubs
S1 made NotificationRecipient.EmailAddress nullable + added SmsConfiguration
and four INotificationRepository SMS methods, breaking compilation beyond the
intentionally-deferred central NotificationRepository.

Fix 1 (CS8620/CS8604 nullable EmailAddress projections, email-only paths):
- NotificationOutbox EmailNotificationDeliveryAdapter: filter non-null emails
- DeploymentManager ArtifactDeploymentService: filter non-null emails
- Transport EntitySerializer: filter non-null emails into NotificationRecipientDto

Fix 2 (CS0535): stub the four SMS-config methods on SiteRuntime
SiteNotificationRepository (central-only — NotSupportedException, matching the
existing 'Managed via artifact deployment from Central' write-path pattern).

Doc nits: reword NotificationRecipient private ctor and SmsConfiguration.AuthToken
comments.

The central ConfigurationDatabase.NotificationRepository compile break is left
as-is (S2 implements those four methods).
2026-06-19 09:51:07 -04:00
Joseph Doherty fb18253f32 fix(deploy): normalize snapshot List values (Decode→Encode) before staleness/diff (#102); CLI --value native-List help 2026-06-19 02:24:26 -04:00
Joseph Doherty b3d99248fa feat(m9/T32b): JSON Schema $ref resolver (lib seam, cycle/depth-guarded) + deploy-time dangling-ref block 2026-06-18 11:54:19 -04:00
Joseph Doherty d45a7a5760 fix(transport): real stale-instance enumeration in ImportResult (M8 D2, #16) + native-alarm rename-redirect test 2026-06-18 07:35:08 -04:00
Joseph Doherty c1043569f6 docs(deployment): reconcile delete-from-NotDeployed — spec matrix now matches deliberate code (#31, M2.17)
git blame shows commit 1d5465f3 deliberately added NotDeployed to CanDelete so an
undeployed instance can have its orphan record fully removed. Code + tests already
permit it; the spec matrix said 'No'. Per M2.17, reconcile doc→code (not the reverse):
matrix now reads 'Delete from Not deployed = Yes (removes the orphan record)' with a
note, and CanDelete carries a remark citing the rationale + origin commit.
2026-06-16 07:24:57 -04:00
Joseph Doherty 7c14a69091 feat(#23): elevate connection-binding completeness to a deploy-gating Error (M2.8)
Pre-deployment validation only WARNED when a data-sourced attribute had no
connection binding, so an instance with unresolved bindings still passed IsValid
and could deploy. There was also no check that a binding resolves to a connection
that actually exists at the target site.

- ValidationService.Validate gains an opt-in `enforceConnectionBindings` flag
  (default false) plus a `siteConnectionNames` set. Default-false keeps the
  template DESIGN-TIME path (ManagementActor.HandleValidateTemplate) non-blocking,
  since bindings are legitimately set later at instance/deploy time. The DEPLOY
  path (FlatteningPipeline) opts in (true) so:
    * a data-sourced attribute with no binding is now a deploy-gating Error;
    * a binding to a connection that does not exist on the target site is an Error.
  Static (non-data-sourced) attributes are never flagged.
- FlatteningPipeline computes the site-connection-names set from the loaded site
  data connections (mirroring M2.1's alarmCapableConnectionNames) and threads it in.
- Tests: TemplateEngine.Tests covers design-time warning / deploy-time error /
  static-ok / exists-at-site / non-existent-connection. New
  FlatteningPipelineConnectionBindingTests proves the deploy path enforces it.

Mark M2.7 + M2.8 completed in the plan task tracker.
2026-06-16 05:28:06 -04:00
Joseph Doherty 41d828e38e fix(deploy): address M2.1 review nits — comparer consistency + comments (#22)
- connection-name capable-set comparer kept as StringComparer.Ordinal:
  FlatteningService and SemanticValidator use all-ordinal name-keyed
  dictionaries throughout; OrdinalIgnoreCase would be inconsistent with
  the rest of the binding-resolution path — added comment documenting this
- IsAlarmCapable protocol-match confirmed consistent with DataConnectionFactory
  (both OrdinalIgnoreCase); added case-insensitive InlineData variants
  (OPCUA, opcua, mxgateway, MXGATEWAY) to lock the contract
- clarified FlatteningPipeline comment: "filters connections by alarm-capable
  protocol, then collects their names" (was "maps from the protocol string")
- added DataConnectionLayer/DataConnectionFactory.cs path reference to
  AlarmCapableProtocols sync-risk comment
2026-06-15 13:27:26 -04:00
Joseph Doherty d6909207a8 fix(deploy): wire native-alarm-source capability validation into flattening pipeline (#22)
FlatteningPipeline loaded data connections but never passed the alarm-capable
connection set to SemanticValidator, so the native-alarm-source capability check
(built but inert) never ran — a source bound to a non-alarm-capable connection
deployed silently. Compute the capable set (IAlarmSubscribableConnection: OPC UA
+ MxGateway) and thread it through ValidationService to SemanticValidator.
2026-06-15 13:20:20 -04:00
Joseph Doherty eabf270d71 docs: complete XML doc coverage (returns, summaries, inheritdoc)
Resolve all 622 issues flagged by the enhanced CommentChecker: add missing
<returns> tags (incl. the standard phrasing on non-generic Task methods),
add missing <summary> tags, and replace misused/redundant <inheritdoc/> on
members that override or implement nothing with real documentation.
Documentation-only — no behavior change; solution builds clean.
2026-06-03 11:39:32 -04:00
Joseph Doherty 877f2e200b feat(scadabridge): emit scadabridge.deployments.applied on deployment success 2026-06-01 16:52:09 -04:00
Joseph Doherty 7b0b9c7365 refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj,
namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated.
ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated.
SQL roles/logins, LDAP domains, CLI command name, and CLI config dir
(~/.scadalink → ~/.scadabridge) also renamed.

Build green; 5 Host.Tests fail awaiting SQL login rename in next commit.
Pre-existing StaleTagMonitor timing flakes unchanged.

Rename script committed at tools/rename-to-scadabridge.sh.
2026-05-28 09:37:45 -04:00