feat(push): add service-owned firebase channels and delivery
Add push contracts, provider delivery and channel diagnostics. Link email channels to services and document migration and validation. Ref: IT-1074
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# 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:
|
||||
|
||||
```bat
|
||||
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.
|
||||
Reference in New Issue
Block a user