# DECISIONS.md — Architecture Decision Log

---

## Phase 0 — Overall Architecture

### 3 Candidates

**Agent 1 (Pragmatic Builder)**
SSE instead of Socket.io; no secret encryption; single flat route file; nodemailer/webhook stubs.
Weighted score: 0.786

**Agent 2 (Robust Systems Architect)**
Socket.io for bi-directional realtime; AES-256 encrypted secrets; layered router/service/repo;
migration-based schema; persistent job state; Electron desktop companion.
Weighted score: 0.845

**Agent 3 (UX Optimizer)**
ninja-keys command palette; template editor with per-platform preview; autosave; per-job status chips;
three-layer failure visibility; test-connection buttons.
Weighted score: 0.740

### Winner: Hybrid (Agent 2 core + Agent 3 UX)

| Component | Source |
|-----------|--------|
| Express layered architecture | Agent 2 |
| better-sqlite3 + migrations | Agent 2 |
| Socket.io for realtime | Agent 2 |
| AES-256 encrypted API keys | Agent 2 |
| Persistent scheduler state | Agent 2 |
| Electron desktop companion | Agent 2 |
| ninja-keys command palette | Agent 3 |
| Per-platform template editor | Agent 3 |
| Three-layer failure visibility | Agent 3 |
| Autosave + toast system | Agent 3 |
| Test-connection button | Agent 3 |

**Rejected alternatives:**
- SSE-only (Agent 1): rejected because AI chat widget needs bidirectional streaming
- Full OAuth (none): out of v1 scope
- Redis queue (none): SQLite job queue is sufficient for this workload

---

## Phase 1 — Database Schema

### Winner: Agent 2 (normalized schema with migration runner)

Tables: api_keys, automations, automation_runs, notifications, templates, audit_log

Decided to store encrypted API keys as `ciphertext` (AES-256-GCM), nonce stored alongside.
Encryption key derived from APP_SECRET env var via PBKDF2.

---

## Phase 2 — Notification Platform Adapters

### Winner: Hybrid (Agent 2 adapter pattern + Agent 3 template model)

Adapters: EmailAdapter, SlackWebhookAdapter, GenericWebhookAdapter
Templates: stored in DB per (platform, automation_id), with {{variable}} substitution.

---
