10 KiB
10 KiB
Task P.7.2 Implementation Report
Scope
This round implements the first working slice of the SMTP / Email Configuration Platform for ALLA OS.
Delivered scope:
- organization-scoped email configuration persistence
- encrypted SMTP password storage
- CRUD APIs for email configurations
- SMTP connection test
- send test email action
- setup readiness / verification integration
- setup wizard optional email status card
- dashboard-native email administration page
- notification runtime integration so email sending uses the stored organization configuration
Review Summary
Reviewed before implementation:
- AGENTS.md
- docs/standards/project-foundations.md
- docs/standards/architecture-rules.md
- docs/standards/ui-ux-rules.md
- docs/standards/task-review-checklist.md
- docs/setup/verification-matrix.md
- docs/setup/setup-wizard-blueprint.md
- docs/setup/installation-profiles.md
- docs/implementation/task-d72-setup-readiness-verification-apis.md
- docs/implementation/task-d76-dashboard-setup-wizard-ui.md
- docs/implementation/task-f4-notification-framework-foundation.md
- docs/implementation/task-p.7.1-implementation.md
Architecture Notes
The implementation intentionally extends the existing notification foundation instead of creating a second outbound-email stack.
Key decisions:
- persisted email configuration is organization-scoped in a new
email_configurationstable - secret encryption is isolated in a reusable helper at src/features/foundation/secrets/server/crypto.ts
- the notification runtime keeps using the existing provider factory, but the email provider now resolves organization SMTP config from the new foundation
- setup readiness and setup verification both read from the same persisted source of truth instead of environment-only
SMTP_*variables - the setup wizard keeps email as an optional operator step, matching the task requirement that email must not block first-run setup by default
Main Changes
1. Data Model And Secret Handling
Added:
Behavior:
- SMTP passwords are stored only as encrypted ciphertext
- API responses never return decrypted or raw password values
- UI only receives
hasPassword - missing or weak
EMAIL_CONFIG_ENCRYPTION_KEYblocks encryption-dependent save paths
2. Email Foundation Services
Added:
- src/features/foundation/email/server/email-provider.ts
- src/features/foundation/email/server/smtp-provider.ts
- src/features/foundation/email/server/email-config.service.ts
- src/features/foundation/email/server/email-test.service.ts
Behavior:
- create, update, list, fetch, and delete email configs
- track default / active config
- test connection and test send update
last_test_status,last_tested_at, and safelast_test_error - audit events are written for create, update, delete, and test outcomes
3. Notification Runtime Integration
Updated:
- src/features/foundation/notifications/server/email-provider.ts
- src/features/foundation/notifications/server/provider-factory.ts
- src/features/foundation/notifications/server/service.ts
Behavior:
- email dispatches now resolve SMTP settings from the active organization configuration
- the provider factory now receives
organizationId - existing notification send / resend flows continue using the established foundation contract
4. Setup Integration
Updated:
- src/features/setup/server/readiness.service.ts
- src/features/setup/server/verification.service.ts
- src/features/setup/components/setup-wizard.tsx
- src/features/foundation/email/components/setup-email-card.tsx
Behavior:
- readiness and verification now check persisted organization email config
- no configuration returns
WARNING, notFAIL, so setup remains non-blocking by default - a lightweight email status card is shown inside the setup wizard and links to the email admin page
5. Admin APIs And UI
Added APIs:
- src/app/api/notifications/email-configurations/route.ts
- src/app/api/notifications/email-configurations/[id]/route.ts
- src/app/api/notifications/email-configurations/[id]/test/route.ts
- src/app/api/notifications/email-configurations/[id]/send-test/route.ts
Added client layer:
- src/features/foundation/email/api/types.ts
- src/features/foundation/email/api/service.ts
- src/features/foundation/email/api/queries.ts
- src/features/foundation/email/api/mutations.ts
Added page:
- src/app/dashboard/administration/email/page.tsx
- src/features/foundation/email/components/email-configuration-page.tsx
- src/config/nav-config.ts
UI notes:
- layout follows dashboard-native card rhythm rather than a separate visual system
- top summary area keeps status scannable
- quick verification panel gives one stable place for test-recipient entry
- config cards separate transport, sender identity, secret state, and test state clearly
- operator notes are intentionally calm and low-noise per task request
Validation
Executed:
npm run typecheck -- --pretty falsenpm run db:generatenpm run test:setupnpx oxlint src/features/foundation/email src/features/foundation/secrets src/features/foundation/notifications/server/email-provider.ts src/features/foundation/notifications/server/provider-factory.ts src/features/setup/server/readiness.service.ts src/features/setup/server/verification.service.ts src/features/setup/components/setup-wizard.tsx src/app/api/notifications/email-configurations src/app/dashboard/administration/email/page.tsx src/config/nav-config.ts
Results:
- TypeScript passed
- Drizzle migration generated successfully
- setup test suite passed
- targeted lint passed
Known Gaps After This Round
- no dedicated profile-level rule yet to force email as a blocking setup requirement for selected installation profiles
- no password reset or invitation flow integration yet; this round only builds the platform and runtime foundation
- no seeded email templates or notification-template management UI specific to outbound email yet
- no per-configuration preview panel for rendered notification payloads yet
- no explicit soft-delete or archived state; delete currently removes the configuration row
Notes
- This implementation assumes
EMAIL_CONFIG_ENCRYPTION_KEYwill be added to runtime environments before operators save SMTP passwords. - Existing unrelated dirty files in the worktree were left untouched.