Implements spec `099-alerts-v1-teams-email`. - Monitoring navigation: Alerts as a cluster under Monitoring; default landing is Alert deliveries. - Tenant panel: Alerts points to `/admin/alerts` and the cluster navigation is hidden in tenant panel. - Guard compliance: removes direct `Gate::` usage from Alert resources so `NoAdHocFilamentAuthPatternsTest` passes. Verification: - Full suite: `1348 passed, 7 skipped` (EXIT=0). Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #121
48 lines
2.6 KiB
Markdown
48 lines
2.6 KiB
Markdown
# Research — 099 Alerts v1 (Teams + Email)
|
||
|
||
This document resolves the Phase 0 technical unknowns from the implementation plan.
|
||
|
||
## Decision: Delivery mechanism (Teams)
|
||
|
||
- **Decision**: Use Laravel HTTP client (`Illuminate\Support\Facades\Http`) to POST JSON to a Teams incoming webhook URL.
|
||
- **Rationale**: The repo already uses the Laravel HTTP client for remote calls (e.g., Microsoft Graph). It provides timeouts and structured error handling, and it keeps delivery logic self-contained.
|
||
- **Alternatives considered**:
|
||
- Guzzle direct client: unnecessary since Laravel HTTP client is already available.
|
||
- Third-party Teams SDK: adds dependency surface; avoid without explicit need.
|
||
|
||
## Decision: Delivery mechanism (Email)
|
||
|
||
- **Decision**: Use Laravel mail/notification delivery and queue it.
|
||
- **Rationale**: Integrates with Laravel queue retries and provides a standard path for SMTP/mail providers.
|
||
- **Alternatives considered**:
|
||
- Direct SMTP calls: not aligned with framework patterns.
|
||
|
||
## Decision: Retry + backoff policy
|
||
|
||
- **Decision**: Implement bounded retries using queued jobs with exponential backoff.
|
||
- **Rationale**: Matches spec FR-017 and constitution guidance for transient failure handling.
|
||
- **Alternatives considered**:
|
||
- Retry loops inline: violates “start surfaces enqueue-only” and increases request latency.
|
||
|
||
## Decision: Secrets storage and redaction
|
||
|
||
- **Decision**: Store destination configuration (webhook URL, recipient list) using Laravel encrypted casts (`encrypted` / `encrypted:array`), and ensure audit/log context is sanitized.
|
||
- **Rationale**: The repo already uses encrypted casting for sensitive payloads (example: `ProviderCredential::$casts['payload' => 'encrypted:array']`). `WorkspaceAuditLogger` sanitizes metadata.
|
||
- **Alternatives considered**:
|
||
- Plaintext storage + hiding in UI: insufficient; secrets can leak to logs/DB dumps.
|
||
|
||
## Decision: Quiet-hours timezone fallback
|
||
|
||
- **Decision**:
|
||
1) Use the rule’s `quiet_hours_timezone` when set.
|
||
2) Else use a workspace-level timezone setting.
|
||
3) If no workspace timezone exists yet, fallback to `config('app.timezone')`.
|
||
- **Rationale**: Implements spec FR-009 while remaining robust if workspace timezone is not yet modeled as a first-class setting.
|
||
- **Alternatives considered**:
|
||
- Always `UTC`: contradicts the clarified requirement (workspace fallback).
|
||
|
||
## Notes / follow-ups
|
||
|
||
- No existing mail delivery usage was found in `app/` at planning time; v1 will introduce the first alert-specific email delivery path.
|
||
- No existing Teams webhook sender was found; v1 will implement a minimal sender using Laravel HTTP client.
|