# FreshCloud Mail — Bundle Features

**Bundle ID:** `freshcloud-mail`
**Bundle version:** 0.1.0
**Last updated:** 2026-07-22
**License:** MIT (per FVW §17.3 `tier: generic`)

This is the human-readable description of the FreshCloud Mail bundle. For the machine-readable manifest, see [`bundle-manifest.json`](./bundle-manifest.json). For the canonical code, see each module's `src/<Namespace>/` in `oscar-platform/modules/`.

---

## What this bundle does

FreshCloud Mail is a **sovereign mail client** for FreshVibe apps. It gives the user a 3-pane inbox: folder list on the left, message list in the middle, message view on the right, plus a compose modal. The mail client is wired to PocketBase for draft persistence, audit logging, and (when configured) real IMAP/SMTP servers.

**The bundle is a complete "mail brain"**: 17 PHP engine modules for the mechanics (parsing, transport, storage), 4 app-layer modules for the wiring (compose, identity, PB adapter, SMTP bridge), and a React chrome (the 3-pane UI) that consumes the bridge at `oscar-platform/api/email/`.

Apps that install the FreshCloud Mail bundle get all of this. Apps that only want the engine (e.g. a CLI tool) can install just the `mail-engine-*` modules.

---

## Features at a glance

| Feature | What it does | Sub-modules involved | Optional? |
|---|---|---|---|
| **folders** | List IMAP folders (Inbox, Sent, Drafts, etc.) | mail-engine-imap-client, mail-engine-imap-commands, mail-engine-cache, mail-app-compose, mail-app-identity | No (required) |
| **messages** | List + read messages in a folder | mail-engine-imap-client, mail-engine-mime-parser, mail-engine-mime-content, mail-engine-mail-client, mail-app-compose | No (required) |
| **compose** | New / reply / forward a message | mail-app-compose, mail-engine-smtp, mail-engine-mime-parser, mail-engine-mail-client, mail-app-identity, mail-app-pocketbase | No (required) |
| **send** | Queue + send via SMTP | mail-engine-smtp, mail-engine-mail-client, mail-app-pocketbase, mail-engine-log | No (required) |
| **drafts** | Save + resume + delete drafts | mail-app-compose, mail-app-pocketbase, mail-engine-log | No (required) |
| **audit** | Log every action to PB email_audit | mail-engine-log, mail-app-pocketbase | No (required) |
| **search** | Search messages in folders | mail-engine-imap-client, mail-engine-mail-client | Yes |
| **filter** | Per-user Sieve rules | mail-engine-sieve, mail-app-pocketbase | Yes |
| **cache** | In-memory + file LRU cache | mail-engine-cache | Yes (recommended for performance) |
| **identity** | Per-user identity lookup | mail-app-identity | No (required) |

---

## Feature → module map

### folders
- **What the user sees:** a list of folders (Inbox, Sent, Drafts, Trash, custom) with unread counts
- **What happens under the hood:**
  1. `mail-app-compose` exposes `/api/email/folders?user_id=X&account_id=Y`
  2. `mail-app-identity` validates the user
  3. `mail-engine-imap-client` connects to the IMAP server (or returns cached data in test mode)
  4. `mail-engine-imap-commands` builds a `LIST "" *` request
  5. `mail-engine-mail-client` aggregates the response
  6. `mail-engine-cache` stores the result for next request
  7. Bridge returns JSON

### messages
- **What the user sees:** a list of messages in a folder (subject, from, date, snippet)
- **What happens under the hood:**
  1. `mail-app-compose` exposes `/api/email/messages?folder=INBOX&page=1&pageSize=50`
  2. `mail-engine-imap-client` runs `SELECT folder` + `FETCH 1:50 (ENVELOPE)`
  3. `mail-engine-mime-parser` parses the envelope (subject, from, date, body preview)
  4. `mail-engine-mime-content` builds the value objects
  5. Bridge returns JSON envelope array

### compose
- **What the user sees:** a modal with To/Subject/Body fields, "Send" and "Save Draft" buttons
- **What happens under the hood:**
  1. User clicks "New" → React chrome calls `POST /api/email/compose/start {mode: "new"}`
  2. `mail-app-compose` returns a `draft_id` (UUID)
  3. User fills the form, clicks "Save Draft" → `PUT /api/email/compose/{id}` with form data
  4. `mail-app-compose` validates, persists to PB `email_drafts` via `mail-app-pocketbase`
  5. `mail-engine-log` records the action to PB `email_audit`
  6. User clicks "Send" → `POST /api/email/compose/{id}/send`
  7. `mail-app-compose` loads the draft, builds the MIME message
  8. `mail-engine-smtp` queues the send (in test mode) or sends via real SMTP (in prod)
  9. `mail-app-pocketbase` records the sent message in `email_outbox`

### drafts
- **What the user sees:** saved drafts in the "Drafts" folder, clickable to resume
- **What happens under the hood:**
  1. `GET /api/email/drafts?user_id=X` returns all drafts from PB `email_drafts` where `user_id = X`
  2. Click a draft → `GET /api/email/compose/{id}` returns the form data
  3. Edit + save → `PUT /api/email/compose/{id}`
  4. Delete → `DELETE /api/email/compose/{id}`

### audit
- **What happens:** every bridge endpoint logs to PB `email_audit` via `mail-engine-log`:
  - `event`: "compose.start" / "compose.save" / "compose.send" / "compose.delete" / "folders.list" / etc.
  - `user_id`: who did it
  - `timestamp`: when
  - `payload`: relevant data (no passwords, no full message bodies)
  - `result`: "ok" or "error:<code>"

### search
- **What it does:** search messages in a folder by subject/from/body
- **Status:** planned, not yet implemented in the engine. The bridge endpoint `/api/email/search` returns a 501 in test mode.

### filter
- **What it does:** per-user Sieve rules that auto-file incoming mail
- **Status:** `mail-engine-sieve` is built and tested, but not yet wired to the bridge. Future work.

### cache
- **What it does:** in-memory LRU + file-based TTL cache for IMAP folder/message responses
- **Why optional:** without it, every folders/messages request hits the IMAP server. With it, the common cases (recently-viewed folder) are O(1) cache lookups.

### identity
- **What it does:** `mail-app-identity` provides a `lookupByEmail($email): ?User` method. The bridge uses it to resolve `user_id` from PB or test fixtures.
- **In test mode:** returns a hardcoded admin user.
- **In prod:** queries PB `users` collection.

---

## Per-app wiring example (Oscar)

```ts
// Oscar's React chrome at app/app-fragments/freshcloud-mail/
import { EmailApp } from '../app-fragments/freshcloud-mail';

// In Oscar's main.tsx
<Route path="/mail" element={<EmailApp />} />
```

```php
// Oscar's bridge at api/email/_bootstrap.php
require_once __DIR__ . '/../../vendor/autoload.php';

// _bootstrap.php wires the Composer with:
// - mail-engine-log (Logger)
// - mail-app-pocketbase (NullPb in test, RealPocketBaseAdapter in prod)
// - mail-engine-smtp (InMemorySmtpClient in test, real SMTP in prod)
// - mail-engine-mail-client (InMemoryMailClient in test, real IMAP in prod)
// - mail-app-identity (test provider in test, real PB in prod)
// - mail-app-compose (the Composer that ties them all)
```

---

## What you get for free when you install this bundle

- ✅ 3-pane mail UI (folders, messages, message view)
- ✅ Compose modal (new / reply / forward)
- ✅ Drafts (save, resume, delete)
- ✅ Send (via real SMTP in prod, queue in test)
- ✅ Audit log (every action recorded)
- ✅ Per-user identity (PB-backed in prod)
- ✅ In-memory + file cache (LRU + TTL)
- ✅ Sieve filter engine (built, not yet wired)
- ✅ Recipe-books for every module (so the bundle can be re-built from scratch)
- ✅ 96+ PHPUnit tests (all green)

---

## What you don't get (and have to wire yourself)

- ❌ The 17 engine modules' canonical home (each lives in `oscar-platform/modules/mail-engine-<name>/` — you don't have to do anything, they're already there)
- ❌ The bridge's auth (currently trusts `user_id` in the body — for production, add PB session/JWT validation)
- ❌ Real IMAP/SMTP credentials (test mode uses InMemory*; production needs server config)
- ❌ Per-user PB email_accounts table (Phase 1.1 work)

---

## License

This bundle is `generic` per FVW §17.3 (MIT-licensed). No license key required. Anyone can install, modify, or ship.

---

## Versioning

- `0.1.0` — initial release. 17 engine modules + 4 app-layer modules. All green tests. Bridge live in Oscar.

Minor versions are backwards compatible. Major versions may include breaking changes to the sub-module APIs.

---

## See also

- `bundle-manifest.json` — machine-readable manifest
- `module.json` — bundle identity + license
- `recipe-book/` — sub-module recipe-books
- `oscar-platform/api/email/` — the bridge endpoints
- `oscar-platform/app/app-fragments/freshcloud-mail/` — the React chrome
- FVW v8.2 §17.5-§17.7 — module canonical home, mirror model, fork/revibe
