feat(ADM-018): completed feature
This commit is contained in:
26
work/artifacts/F-024/architect.md
Normal file
26
work/artifacts/F-024/architect.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Architect — F-024 Notifications: transactional email
|
||||
|
||||
## Feature
|
||||
F-024 sends transactional emails driven by domain events with idempotency per event id and a swappable provider.
|
||||
|
||||
## Design
|
||||
|
||||
### Module boundaries
|
||||
Create `project/src/modules/notifications/` with domain/application/infrastructure/api/tests. Notifications owns message persistence and provider dispatch; domain code uses only the `EmailProvider` interface.
|
||||
|
||||
### Data model
|
||||
Add migration `018_notifications.js`:
|
||||
- `notifications_messages`: id, event_id text unique, channel text default 'email', template text, recipient text, subject text, body text, status text default 'sent', created_at timestamptz.
|
||||
- UNIQUE `event_id` for idempotency.
|
||||
|
||||
### Templates
|
||||
- `order_confirmation`, `payment_failed`, `order_shipped` mapped to events `OrderPaid`, `PaymentFailed`, `OrderShipped`.
|
||||
|
||||
### API
|
||||
- Internal `/notifications/dispatch` (admin/test) to trigger a dispatch by template and recipient.
|
||||
- Internal `/notifications/messages/:eventId` to inspect dispatch status.
|
||||
|
||||
## Acceptance trace
|
||||
- PaymentSucceeded -> order_confirmation email queued, idempotent on event_id.
|
||||
- Replay same event -> no duplicate row.
|
||||
- Provider swap touches only infrastructure.
|
||||
26
work/artifacts/F-024/documenter.md
Normal file
26
work/artifacts/F-024/documenter.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Documenter — F-024 Notifications: transactional email
|
||||
|
||||
## Summary
|
||||
Notifications module dispatches transactional emails through an EmailProvider port. event_id is the idempotency key for retries. Provider implementations live in infrastructure.
|
||||
|
||||
## Public API notes
|
||||
|
||||
| Route | Access | Result |
|
||||
|---|---|---|
|
||||
| POST /notifications/dispatch | admin | Records message and triggers provider.send |
|
||||
| GET /notifications/messages/:eventId | admin | Returns stored message status |
|
||||
|
||||
## Templates
|
||||
- `order_confirmation`
|
||||
- `payment_failed`
|
||||
- `order_shipped`
|
||||
|
||||
## Errors
|
||||
- `NOT_FOUND` — HTTP 404 when querying unknown event_id
|
||||
|
||||
## Evidence
|
||||
- `work/artifacts/F-024/architect.md`
|
||||
- `work/artifacts/F-024/implementer.md`
|
||||
- `work/artifacts/F-024/reviewer.json`
|
||||
- `work/artifacts/F-024/security.json`
|
||||
- `work/artifacts/F-024/qa.json`
|
||||
23
work/artifacts/F-024/implementer.md
Normal file
23
work/artifacts/F-024/implementer.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Implementer — F-024 Notifications: transactional email
|
||||
|
||||
## Summary
|
||||
Implemented notifications module with `NotificationsService` dispatching email through an `EmailProvider` port. `notifications_messages.event_id` enforces idempotency. Provider is injected at composition root so swapping providers only touches infrastructure.
|
||||
|
||||
## Files changed
|
||||
- `project/migrations/018_notifications.js`
|
||||
- `project/src/modules/notifications/**`
|
||||
- `project/src/app/build-app.ts`
|
||||
|
||||
## Acceptance evidence
|
||||
- AC1 dispatch on first event: `notifications-service.test.ts` confirms first call returns 'sent' and provider.send called once.
|
||||
- AC2 replay no duplicate: same test injects `findByEventId` returning an existing row and asserts 'duplicate' with no second provider call.
|
||||
- AC3 provider swap: `boundary.test.ts` asserts only `infrastructure/` references `LoggingEmailProvider` or `emailProvider.send`.
|
||||
|
||||
## Commands run
|
||||
- `cd project && npm run lint/typecheck/build/test` passed
|
||||
- `cd project && TEST_DATABASE_URL='postgres://mdv:mdv_dev_only@localhost:5432/mdv_test' npm run test:integration -- migrations.itest` passed; 14 files, 53 tests
|
||||
- `./scripts/verify.sh` passed
|
||||
|
||||
## Notes
|
||||
- No new runtime dependency.
|
||||
- `LoggingEmailProvider` writes JSON lines for v1.
|
||||
15
work/artifacts/F-024/leader-close.json
Normal file
15
work/artifacts/F-024/leader-close.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"feature_id": "F-024",
|
||||
"agent": "leader",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "F-024 closed with reviewer, security and QA gates approved. Final verify.sh passed.",
|
||||
"evidence": [
|
||||
"reviewer.json verdict APPROVED",
|
||||
"security.json verdict APPROVED",
|
||||
"qa.json verdict APPROVED",
|
||||
"./scripts/verify.sh passed during close",
|
||||
"backlog/features.json updated: F-024 status done and gates true",
|
||||
"work/current.md updated: no active feature, next suggested F-025"
|
||||
],
|
||||
"timestamp": "2026-08-15T18:48:25Z"
|
||||
}
|
||||
20
work/artifacts/F-024/qa.json
Normal file
20
work/artifacts/F-024/qa.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"feature_id": "F-024",
|
||||
"agent": "qa",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "QA approved. All F-024 acceptance criteria are covered by executable tests and green checks.",
|
||||
"evidence": [
|
||||
"notifications-service.test.ts covers first-event sent and replay duplicate",
|
||||
"boundary.test.ts proves only infrastructure references LoggingEmailProvider",
|
||||
"cd project && npm run lint/typecheck/build/test passed",
|
||||
"DB integration migrations suite passed: 14 files, 53 tests",
|
||||
"./scripts/verify.sh passed"
|
||||
],
|
||||
"acceptance": [
|
||||
{ "criterion": "Given PaymentSucceeded event When processed Then order confirmation email queued", "status": "PASS", "evidence": "notifications-service dispatches on first event and template order_confirmation maps to OrderPaid" },
|
||||
{ "criterion": "Given same event redelivered When processed Then no duplicate email", "status": "PASS", "evidence": "service returns 'duplicate' on existing event_id and provider.send is not called again" },
|
||||
{ "criterion": "Swapping email provider touches only infrastructure adapter", "status": "PASS", "evidence": "boundary.test.ts confirms only infrastructure files reference the provider implementation; route uses EmailProvider port" },
|
||||
{ "criterion": "verify.sh green", "status": "PASS", "evidence": "./scripts/verify.sh PASS" }
|
||||
],
|
||||
"timestamp": "2026-08-15T18:48:04Z"
|
||||
}
|
||||
18
work/artifacts/F-024/reviewer.json
Normal file
18
work/artifacts/F-024/reviewer.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"feature_id": "F-024",
|
||||
"agent": "reviewer",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "F-024 review approved. Notifications module exposes an EmailProvider port, idempotently records messages by event_id, and keeps provider implementation behind infrastructure. Route handlers accept only admin role.",
|
||||
"evidence": [
|
||||
"Read work/current.md, architect.md and implementer.md",
|
||||
"Inspected notifications domain/application/infrastructure/API and migration 018_notifications.js",
|
||||
"Verified event_id UNIQUE in schema and ON CONFLICT DO NOTHING in repository",
|
||||
"Verified EmailProvider injected at composition root; API route only depends on the port",
|
||||
"Verified tests cover first-event sent, replay duplicate and provider swap boundary",
|
||||
"gentle-ai review mode status: receipt-driven development off globally, ordinary Orquestra gate used",
|
||||
"cd project && npm run lint/typecheck/build/test passed",
|
||||
"DB integration migrations suite passed: 14 files, 53 tests",
|
||||
"./scripts/verify.sh passed"
|
||||
],
|
||||
"timestamp": "2026-08-15T18:48:04Z"
|
||||
}
|
||||
13
work/artifacts/F-024/security.json
Normal file
13
work/artifacts/F-024/security.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"feature_id": "F-024",
|
||||
"agent": "security",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "Security approved. No new dependencies. Notifications dispatch is admin-only, request schema strips unknown fields, SQL is parameterized, and idempotency is enforced at the database level.",
|
||||
"evidence": [
|
||||
"cd project && npm audit --audit-level=high --omit=dev: found 0 vulnerabilities",
|
||||
"Reviewed /notifications/dispatch and /notifications/messages/:eventId: requireRole admin",
|
||||
"Reviewed schema: strip() and bounded validators",
|
||||
"Reviewed SQL: parameterized queries only"
|
||||
],
|
||||
"timestamp": "2026-08-15T18:48:04Z"
|
||||
}
|
||||
Reference in New Issue
Block a user