TenantAtlas/specs/099-alerts-v1-teams-email/research.md
2026-02-18 15:25:14 +01:00

2.6 KiB
Raw Blame History

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 rules 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.