docs(code-review): record SMS-feature review findings + reconcile NotificationService doc
Per-module code review of the SMS notifications feature (reviewed at d6ead8ae) following
code-reviews/REVIEW-PROCESS.md. 19 findings across 7 modules — 1 High, 5 Medium, 13 Low:
- ManagementService-024 (High): provider-config updates Admin-gated to match the UI.
- ConfigurationDatabase-025, CentralUI-034/035, ManagementService-025 (Medium): migration
data-safety guard, type-aware recipient badge, FromNumber-optional (Messaging-Service-only),
empty-token-clear guard.
- Remaining Low: secret-encryption + diff + dispatch + factory + contract tests, truncation,
ctor guard, reserved retry-field docs.
- Won't Fix: Transport-015/016 (shared repo-wide import patterns, not SMS-specific),
Commons-026 (breaking ergonomics-only change). Deferred: ConfigurationDatabase-027 (live-SQL
migration test).
All findings closed (0 pending). README.md regenerated; Component-NotificationService.md
updated for the FromNumber-optional + reserved-retry-fields outcomes.
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
| Module | `src/ZB.MOM.WW.ScadaBridge.CentralUI` |
|
||||
| Design doc | `docs/requirements/Component-CentralUI.md` |
|
||||
| Status | Reviewed |
|
||||
| Last reviewed | 2026-05-28 |
|
||||
| Last reviewed | 2026-06-19 |
|
||||
| Reviewer | claude-agent |
|
||||
| Commit reviewed | `1eb6e97` |
|
||||
| Commit reviewed | `d6ead8ae` |
|
||||
| Open findings | 0 |
|
||||
|
||||
## Summary
|
||||
@@ -1595,3 +1595,93 @@ advances to Step 2 without opening a session; a wrong passphrase increments the
|
||||
counter and writes the `BundleImportUnlockFailed` audit row; the lockout resets
|
||||
the wizard to Step 1 once `MaxUnlockAttemptsPerSession` is reached; a successful
|
||||
unlock resets the counter and advances to Step 3.
|
||||
|
||||
#### Re-review 2026-06-19 (commit `d6ead8ae`) — SMS notifications feature
|
||||
|
||||
Per-module review of the CentralUI SMS surface: the `/notifications/sms` Admin-only config page, the
|
||||
adapter-gated Type selector + per-type recipient input on the list form, the Type column, and the
|
||||
Transport-export SMS-config selection. Security is solid — the page is `RequireAdmin`, the AuthToken is
|
||||
never rendered (presence-only) and never pre-filled, preserve-if-blank is correct. Two Medium
|
||||
correctness findings and one Low test gap; all Resolved.
|
||||
|
||||
### CentralUI-034 — Notification Lists recipient badge renders "Name <>" for SMS recipients
|
||||
|
||||
| | |
|
||||
|--|--|
|
||||
| Severity | Medium |
|
||||
| Category | Correctness & logic bugs |
|
||||
| Status | Resolved |
|
||||
| Location | `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationLists.razor:70` |
|
||||
|
||||
**Description**
|
||||
|
||||
The recipient badge rendered `@r.Name <@r.EmailAddress>` unconditionally. An SMS recipient carries a
|
||||
PhoneNumber and a null EmailAddress, so an SMS list rendered "Jane <>" — an empty contact field. The
|
||||
same commit added the Type column to this page but did not make the badge type-aware (the list form's
|
||||
recipients table WAS made type-aware; only this summary page was missed).
|
||||
|
||||
**Recommendation**
|
||||
|
||||
Make the badge type-aware: show PhoneNumber for SMS lists, EmailAddress otherwise.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Resolved 2026-06-19 (commit `cd8e4872`): the badge now selects the contact field by `list.Type` (phone
|
||||
for SMS, email otherwise). Locked by `SmsListRecipientBadge_ShowsPhoneNumber_NotEmptyAngleBrackets`
|
||||
(commit `a9393c89`).
|
||||
|
||||
### CentralUI-035 — SMS config Save hard-required a From Number, contradicting the either-or contract
|
||||
|
||||
| | |
|
||||
|--|--|
|
||||
| Severity | Medium |
|
||||
| Category | Correctness & logic bugs |
|
||||
| Status | Resolved |
|
||||
| Location | `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/SmsConfiguration.razor:219` |
|
||||
|
||||
**Description**
|
||||
|
||||
`Save()` required a From Number unconditionally, but the design doc and the Twilio delivery adapter
|
||||
treat FromNumber and MessagingServiceSid as either-or (the adapter only errors when BOTH are blank, and
|
||||
uses the Messaging Service SID instead of From when set). An admin could not create a Twilio
|
||||
Messaging-Service-only configuration through the UI, despite the entity and adapter supporting it.
|
||||
Investigation found the drift ran deeper than the UI: the entity ctor and the EF `FromNumber` column
|
||||
were also non-null, so a pure UI fix was insufficient.
|
||||
|
||||
**Recommendation**
|
||||
|
||||
Reconcile the implementation with the spec — make FromNumber optional end-to-end (entity, schema, UI,
|
||||
CLI) so a Messaging-Service-only config is valid, with at-least-one-of (FromNumber, MessagingServiceSid)
|
||||
validated at the boundaries.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Resolved 2026-06-19 (commit `33e1802e`): made FromNumber optional end-to-end — `SmsConfiguration.FromNumber`
|
||||
→ nullable (ctor param optional), EF `IsRequired(false)` + migration `SmsFromNumberOptional` (ALTER
|
||||
COLUMN nullable), `SmsConfigDto.FromNumber` → nullable, `UpdateSmsConfigCommand.FromNumber` → nullable,
|
||||
UI validation now requires AccountSid + at-least-one-of(FromNumber, MessagingServiceSid), and CLI
|
||||
`--from-number` is conditionally validated. Direction chosen by the design owner.
|
||||
|
||||
### CentralUI-036 — No test for the From-Number/Messaging-Service-SID either-or rule
|
||||
|
||||
| | |
|
||||
|--|--|
|
||||
| Severity | Low |
|
||||
| Category | Testing coverage |
|
||||
| Status | Resolved |
|
||||
| Location | `tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/SmsConfigurationPageTests.cs` |
|
||||
|
||||
**Description**
|
||||
|
||||
No test pinned the sender-identity validation, so the divergence in CentralUI-035 (UI stricter than the
|
||||
adapter contract) was not caught.
|
||||
|
||||
**Recommendation**
|
||||
|
||||
Add a test that saving succeeds with a Messaging Service SID and no From Number.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Resolved 2026-06-19 (commit `33e1802e`): added `SavingNewConfig_MessagingServiceSidOnly_NoFromNumber_Saves`,
|
||||
which asserts the config persists with a null FromNumber. Complemented by ManagementActor + CLI
|
||||
either-or tests in the same commit.
|
||||
|
||||
Reference in New Issue
Block a user