Commit Graph

959 Commits

Author SHA1 Message Date
Joseph Doherty 33e1802e6d feat(sms): make FromNumber optional — support Twilio Messaging-Service-only configs (UI-Med-2)
Code-review finding UI-Med-2: the design doc + delivery adapter treat FromNumber and
MessagingServiceSid as either-or, but the entity ctor, EF schema, UI and CLI all hard-
required FromNumber — so a Messaging-Service-only Twilio config (a normal production
setup) could not be created. Bring the implementation into line with the spec:

- Commons: SmsConfiguration.FromNumber -> string? (ctor fromNumber optional);
  UpdateSmsConfigCommand.FromNumber -> string?.
- ConfigurationDatabase: FromNumber.IsRequired(false) + migration SmsFromNumberOptional
  (ALTER COLUMN nullable, idempotent; Down backfills '' — harmless, MsgSid keeps it
  deliverable) + regenerated model snapshot.
- Transport: SmsConfigDto.FromNumber -> string? (round-trips a Messaging-Service-only config).
- CentralUI: form validation requires AccountSid + at-least-one-of(FromNumber, MsgSid);
  nullable create/edit paths; From-number help text.
- CLI: --from-number no longer Required; BuildUpdateSmsConfigCommand validates the either-or.
- Adapter: From branch null-forgiving (guarded by the existing incomplete-config check).

Tests: ManagementActor MsgSid-only persists null FromNumber; CLI MsgSid-only builds +
neither-throws + contract (--from-number not Required); CentralUI MsgSid-only save.
2026-06-19 15:19:40 -04:00
Joseph Doherty a9393c8913 test(sms): regression tests for code-review fixes
Lock the behaviors changed by the review-fix commit + the security invariants:

- ManagementActorTests: UpdateSms/SmtpConfig now require Administrator (updated the
  existing success cases from Designer); + UpdateSmsConfig_WithDesignerRole_Returns
  Unauthorized and _WithEmptyAuthToken_PreservesExistingToken regression tests.
- SecretEncryptionTests: SmsConfiguration.AuthToken stored-encrypted round-trip +
  null round-trip (AccountSid stays plaintext) — guards ApplySecretColumnEncryption.
- ArtifactDiffTests: CompareSmsConfiguration New/Identical/Modified + the secret
  presence-only invariant (value never echoed, presence-flip shows <present> only).
- UpdateCommandContractTests: notification sms update core fields Required, --auth-token optional.
- NotificationListsPageTests: SMS recipient badge shows phone, not "Name <>".
- NotificationOutboxActorDispatchTests: SMS-typed notification routes to the SMS
  adapter (StubAdapter.Type made configurable), not the Email adapter.
- NotificationRecipientTests (new): ForEmail/ForSms + public-ctor invariants.
2026-06-19 15:09:47 -04:00
Joseph Doherty d6ead8ae62 test(sms): live Playwright E2E for SMS config page + Type selector + Type column (S11) 2026-06-19 11:54:25 -04:00
Joseph Doherty f8e2d7a934 test(sms): de-race NotificationOutbox load-flake under parallel-suite CPU oversubscription (S11) 2026-06-19 11:40:55 -04:00
Joseph Doherty 9558d98343 feat(sms): export wizard SMS-config selection (S10c) 2026-06-19 11:16:32 -04:00
Joseph Doherty c3501ecd72 feat(sms): complete SmsConfig bundle export/import wiring + GetSmsConfigurationByIdAsync (S10b) 2026-06-19 11:10:39 -04:00
Joseph Doherty 78fadb82d2 test/fix(sms): scope S8 Type-column assertion + S9 RetryDelay display (review polish) 2026-06-19 11:00:06 -04:00
Joseph Doherty 4860aeff62 feat(sms): SMS configuration Central UI page + nav (S9) 2026-06-19 10:52:56 -04:00
Joseph Doherty 538117d114 fix(sms): reject notification-list Type change on update (S6 review follow-up) 2026-06-19 10:51:58 -04:00
Joseph Doherty 58ac06a358 feat(sms): NotificationLists Type column (S8) 2026-06-19 10:51:11 -04:00
Joseph Doherty 73df322a66 feat(sms): CLI list --type/--phones + notification sms group + channel-aware recipients (S6) 2026-06-19 10:40:09 -04:00
Joseph Doherty cdfd0ffbd2 feat(sms): Transport recipient PhoneNumber + SmsConfig round-trip (S10) 2026-06-19 10:39:12 -04:00
Joseph Doherty f0c69aad83 feat(sms): NotificationListForm adapter-gated Type selector + per-type recipients (S7) 2026-06-19 10:38:29 -04:00
Joseph Doherty 4555a3f333 test(sms): harden S3 adapter secret-redaction + coverage (review follow-up) 2026-06-19 10:28:58 -04:00
Joseph Doherty a1d484a5ff feat(sms): Twilio SmsNotificationDeliveryAdapter + classifier + options + DI (S3) 2026-06-19 10:14:52 -04:00
Joseph Doherty 609bdb37ef feat(sms): list Type + SMS-config management commands/handlers (S5) 2026-06-19 10:12:55 -04:00
Joseph Doherty bffbb0c2da feat(sms): stamp Notification.Type from list at ingest (S4) 2026-06-19 10:11:05 -04:00
Joseph Doherty 3827b98484 fix(sms): S2 review — add DeleteSmsConfigurationAsync + schema/repo tests + doc nit 2026-06-19 10:06:44 -04:00
Joseph Doherty c5378f8723 feat(sms): NotificationType.Sms + recipient phone + SmsConfiguration + repo iface (S1) 2026-06-19 09:42:27 -04:00
Joseph Doherty c72d7b7902 test(dcl): de-race MxGateway Unsubscribe stops-routing under load (#288) 2026-06-19 05:01:42 -04:00
Joseph Doherty 84cb8c2abb test(comm): de-race StreamRelay null-map + SiteConnectionUp gauge under load (#288) 2026-06-19 05:00:13 -04:00
Joseph Doherty f08a4d609f test(playwright): M9 surface coverage — template search, schema-library, move-connection (#263) 2026-06-19 04:31:38 -04:00
Joseph Doherty c68b9cccd2 test(playwright): harden #230 line-diff test — force-open nested details, robust +/- hunk assert
Live-run fixes: nested <details> made the summary selector ambiguous (strict-mode);
force every disclosure open via JS. Drop the brittle specific-line-text ('99') assert
(depends on CLI-seeded bodies) for a ≥1 add-hunk + ≥1 remove-hunk count check. (#230)
2026-06-19 04:27:20 -04:00
Joseph Doherty 529921f2de test(playwright): M8 import Map step + per-line diff coverage (#230) 2026-06-19 04:23:12 -04:00
Joseph Doherty 4b8986036e test(dcl): deterministic stale-generation reseed-drop after second failover (DCL-027 #233) 2026-06-19 03:39:19 -04:00
Joseph Doherty e814bf5efb fix(ui): per-field sub-schema for escape-hatch Monaco editors + dispose guard (#261) 2026-06-19 03:28:58 -04:00
Joseph Doherty 282bc8b53c fix(ui): templates root-menu Escape + double-menu guard + reorder disabled tests (#258)
- Root context menu now has tabindex/focus + Escape-key close (OnRootMenuKeyDown) mirroring the node menu
- Opening root menu calls _tree.DismissNodeContextMenu(); opening node menu fires OnNodeContextMenuOpened → DismissRootContextMenu so only one menu is ever visible
- Add FolderContextMenu_MoveUp_IsDisabled_OnFirstSibling and FolderContextMenu_MoveDown_IsDisabled_OnLastSibling bUnit tests
2026-06-19 03:28:18 -04:00
Joseph Doherty 8f85cce298 fix(ui): schema-library delete-audit name + busy guard + edit-row guard + sanitized create-race test (#260) 2026-06-19 03:28:11 -04:00
Joseph Doherty e3b83f8561 fix(cli): guard min-time overflow + normalize 0 exec-timeout to null + stale comment (#54 review) 2026-06-19 03:24:11 -04:00
Joseph Doherty 597d664a53 fix(cli): warn on --trigger-kind without --trigger-config (#257)
InjectAnalysisKind returns null on a null/empty trigger-config, so passing
--trigger-kind strict WITHOUT --trigger-config silently dropped the kind on
template script add/update and template alarm update. The CLI now detects that
combination (TriggerKindWillBeIgnored) and prints a clear warning to stderr,
then continues (warn-and-continue: the kind is advisory metadata, not a required
field, so the entity is still created — just without the requested analysis kind).
The --trigger-kind help text on all three commands now documents that it requires
--trigger-config, as does the CLI README.

This commit also carries the shared CLI command-builder file (Commands/TemplateCommands.cs)
and README, which the same builders edit for both #257 and the #54 flag additions —
the #54 message contracts/handler/UI/tests landed in the preceding commit.

- TriggerKindWillBeIgnored predicate + WarnIfTriggerKindIgnored stderr warning,
  wired into script add/update and alarm update SetActions.
- Shared option descriptions document the --trigger-config requirement.
- Adds the #54 CLI flags (--min-time-between-runs, --execution-timeout-seconds) and
  TryParseMinTimeBetweenRuns to the same builder file.
- Tests: TemplateTriggerKindIgnoredTests pins the warn predicate.
2026-06-19 03:14:24 -04:00
Joseph Doherty ae25b5a8d6 feat(cli): add --execution-timeout-seconds + --min-time-between-runs to template script (#54)
Expose TemplateScript.ExecutionTimeoutSeconds and MinTimeBetweenRuns (previously
settable only via Transport bundle import) on the CLI and Central UI authoring surfaces.

- Commons: add additive trailing optionals MinTimeBetweenRuns (TimeSpan?) and
  ExecutionTimeoutSeconds (int?) to Add/UpdateTemplateScriptCommand.
- ManagementActor: thread both new fields into the built TemplateScript on add/update.
- CLI template script add/update: new --min-time-between-runs (duration: ms/s/min,
  bare number = seconds, 0 = unset, mirroring DurationInput) and
  --execution-timeout-seconds (int) flags, with client-side duration validation.
- Central UI TemplateEdit: add an Execution timeout input (seconds) on the script
  trigger tab, mirroring the existing Min-time-between-runs control; null/0 = site default.
- Tests: TemplateScriptTimingTests pins the option surface + duration parsing; updated
  the stale 'no UI control' comment on the TemplateService round-trip test.
2026-06-19 03:14:10 -04:00
Joseph Doherty 5185486a3c fix(deploy): include ElementDataType in RevisionHashService.HashableAttribute (#290)
Fold a List attribute's ElementDataType into the hashable projection so a
change to the element type (e.g. Int32 -> Double) with identical JSON-encoded
values is detected as a staleness/revision change. Inserted in alphabetical
position; null ElementDataType (scalars) is omitted by the canonical
serializer (WhenWritingNull), so scalar-only configs hash identically to
before. DiffService.AttributesEqual gains the same comparison to keep the
structured diff in parity with the staleness hash. Adds tests for differing
vs. equal ElementDataType (hash + diff) and the scalar no-op guard.
2026-06-19 03:07:06 -04:00
Joseph Doherty 79fe098886 test(transport): regression — empty-ConnectionName binding skipped on import (#229) 2026-06-19 03:06:10 -04:00
Joseph Doherty 69e0d546b5 fix(audit): route SecuredWrite audit via ICentralAuditWriter for SourceNode stamping (#206) 2026-06-19 02:37:48 -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 454e47ea38 fix(mgmt): pass sharedScripts to design-time template $ref validation (#259) 2026-06-19 02:21:15 -04:00
Joseph Doherty d844405cec fix(templates): hoist (DataType,ElementDataType,Value) attribute validation into TemplateService (#92) 2026-06-19 02:19:35 -04:00
Joseph Doherty 47f5ca687c refactor(commons): consolidate List element-type/coercion into AttributeValueCodec; InstanceActor + CLI reuse it (#93) 2026-06-19 02:03:09 -04:00
Joseph Doherty 2935c41bf7 fix(inbound-api): recursively coerce nested Object/List values to typed CLR (#55) 2026-06-19 02:02:10 -04:00
Joseph Doherty 3d4521f250 fix(configdb): make ResyncLdapGroupMappingSeed migration idempotent (guarded insert) (#70) 2026-06-19 01:51:20 -04:00
Joseph Doherty f4e03ce8f7 fix(site-runtime): normalize routed GetAttributes List values for cross-process transport (#162) 2026-06-19 01:49:38 -04:00
Joseph Doherty a1eed1c2ab fix(templates): gate resolver HiLo-merge on both-HiLo to match flattener (#262)
Change `mergeEffective` delegate in `ResolveWinners<T>` from `Func<string?, T, string?>`
to `Func<Winner<T>, T, string?>` so the alarm hook can inspect the existing winner's row.
Gate the per-setpoint merge in `ResolveAlarmWinners` on both sides being HiLo
(`existingWinner.Row.TriggerType == HiLo && derived.TriggerType == HiLo`), matching
`FlatteningService.ResolveInheritedAlarms` exactly. Base non-HiLo + derived HiLo now
falls through to whole-replace (derived config verbatim) — the same path the flattener
takes. Preview-only fix; the deploy path is unchanged.

Add test: `Resolve_BaseNonHiLo_DerivedHiLo_DerivedConfigWinsVerbatim` — asserts
resolver and flattener agree when base is ValueMatch and derived overrides to HiLo.
2026-06-19 01:49:25 -04:00
Joseph Doherty 5585d7ba51 test(#53): follow inline→Commons dedup — relocate OpcUa/MxGateway literal coverage to AlarmCapableProtocolsTests; pin TemplateEdit delegation 2026-06-19 01:42:37 -04:00
Joseph Doherty 72e084f588 fix(configdb): GetInstanceBy{Id,UniqueName}Async include NativeAlarmSourceOverrides (#226) 2026-06-19 01:32:10 -04:00
Joseph Doherty 78360eb6a7 test(dcl): strengthen DCL002 derace — 30s AwaitCondition + non-parallel collection for full-suite load (#234) 2026-06-19 01:04:36 -04:00
Joseph Doherty 6a4c9a85b8 fix(notification-outbox+test): provider-aware InsertIfNotExists for SQLite + supply ApiKeyPepper in IntegrationTests host config (#286) 2026-06-19 01:03:48 -04:00
Joseph Doherty 649e45b5c0 test(transport-integration): register ISharedSchemaRepository for FlatteningPipeline in BundleImporterApply fixture (#287, M9-T32 injection regression) 2026-06-19 01:02:58 -04:00
Joseph Doherty 48dfb875bd test(centralui): fix stale List-override round-trip assertion to mirror the page's real string-row encode cycle (CASE A) (#163) 2026-06-19 00:38:06 -04:00
Joseph Doherty 2b2c1b264a test(centralui): mirror production canonical AttributePath==AttributeName in DebugViewStreamRaceTests (#177) 2026-06-19 00:36:59 -04:00
Joseph Doherty 7674b37a24 test(dcl): stabilize flaky DCL002 crash/restart subscription-preservation with condition-based wait (#234) 2026-06-19 00:33:48 -04:00