Add push contracts, provider delivery and channel diagnostics. Link email channels to services and document migration and validation. Ref: IT-1074
4.9 KiB
Email channels: stable service association
Email channels reference services.id (UUID) through required email_channels.service_id.
The (service_id, priority) index supports channel selection; the service FK uses RESTRICT,
so service deletion cannot remove channels or their usage. Service names in channel reads
come from the related service, not a copied string. Create/Edit select an existing service;
Edit can reassign a channel without changing its identity or statistics.
Migration
LinkEmailChannelsToServices validates every legacy channel name before replacing the
string column. An exact, case-sensitive service-name match is accepted. The owner-approved
legacy mapping StoreMate-Prod → Invemory-Prod is also accepted; the existing staging
name Invemory.Staging.Sandbox uses an exact match. Every channel must have exactly one
candidate service. Missing names or ambiguity (for example both legacy and renamed
services existing) abort the migration. No service is guessed, created, renamed or deleted.
The migration runs in an EF transaction and locks services/channels while checking and backfilling. Failure rolls back schema and data. Channel IDs, SMTP settings (including secrets and sender settings), priority, quotas, warning threshold, active state, timestamps and usage records remain unchanged. No SMTP settings are logged by the migration. Downgrade reconstructs the current service names; historical names are not restored.
Before a separately authorized rollout, audit unmatched/ambiguous names and resolve them
with the owner, take the normal backup, and coordinate Web/Worker downtime with migration:
old binaries use the removed service_name column. Administrative POST/PUT clients must
send serviceId; name-only writes are no longer supported. RabbitMQ producers retain
their existing ServiceName wire field and must send the current service name. The
approved legacy mapping applies only during migration, never as a runtime fallback.
Verification
Local database update on Windows
Run from any directory, without arguments or environment setup:
C:\projects\HrynCo\hrynco-notification-service\HrynCo.NotificationService.DAL.EF\update-development-database.bat
The script resolves its directory through %~dp0, reads the existing Web
appsettings.Development.json, builds the EF project in Release and applies pending
migrations. It requires dotnet-ef and Windows PowerShell. It validates a loopback host and a nonempty database name before invoking EF.
The port and database come from the Development configuration without hardcoded overrides.
A remote host is rejected; this script is specifically for the local development database. It never installs, recreates or restarts containers.
The connection is passed only through the child process's App__ConnectionString;
the design-time factory reads it. Credentials are neither echoed nor passed as CLI
arguments, and inherited connection overrides are replaced with the verified Development
configuration. The script returns EF's exit code (or a nonzero code for configuration
failure). Restart local Web/Worker after a schema change to use matching binaries.
Tests
PostgreSQL integration tests exercise exact and approved-alias backfill, preserved channel settings/limits/usage, downgrade, missing/ambiguous-name rollback, FK enforcement, service rename, API validation, editable reassignment with a blank password, and service deletion after reassignment. Worker tests verify name-to-ID channel resolution and sending/usage. All migration rehearsals use disposable local databases; they do not alter production.
On 2026-10-24, the Release solution build, 54 service/worker tests and 145 integration tests passed. A follow-up check explicitly verified both invalid update IDs reach the service-existence validator (2/2 passed). Rider inspected the changed production methods; remaining findings were existing/style suggestions. Cognitive complexity was reviewed structurally against the limit of 10; no numeric score was produced by the inspection.
After separate owner authorization, the existing local container database was backed up
and updated with the already-built Migrator. Its two pending migrations were
20261023223753_AddPushDeliveries and 20261024073202_LinkEmailChannelsToServices.
No email channels or usage records existed in this local database before the update;
their unchanged empty state and the installed RESTRICT FK were verified afterwards.
The development batch script was then executed from its own folder and another working
directory: both returned 0 and reported no pending migrations. An isolated fake EF
failure verified exit-code propagation (37). The current local Web at port 5188 rendered
the dropdown with the existing service catalog. Disposable test containers were removed.
Production was not accessed or migrated.
The existing private-network administration access model is unchanged. This change does not configure Firebase or resume the paused push-channel architecture.