# FreshCloud — research + design exploration

**Status**: Design exploration, not yet a plan. Phases 1-4 are sketched but not committed.

**Author**: Mavis (session 413171774529758)
**Date**: 2026-07-18
**Operator input**: Multi-turn conversation, 2026-07-18 01:24-01:47 UTC

## The big insight (locked)

FreshCloud is **not a separate product**. FreshCloud is Oscar's groupware layer.

What this means concretely:
- One domain (`oscar.freshvibeapps.com`)
- One app (Oscar)
- One auth flow (PB → portal → Oscar → FreshCloud)
- One design language (tiny-icon compact, Oscar's style)
- One mobile story (React Native Oscar, all surfaces baked in)
- One deployment (one VPS, one vhost, one TLS cert, one PB row)

The user-facing experience of email, calendar, contacts, files is **part of Oscar**, not a separate app bolted on. FreshCloud provides the data plane (IMAP/SMTP, CalDAV/CardDAV/WebDAV, storage, sync) and the API bridge. The UI is Oscar's React components.

## Why this is the right shape

1. **One login** — Mark's wife logs into Oscar, sees her email + her calendar + her files. No second password, no second URL, no second app to learn.
2. **One design** — SnappyMail skin doesn't leak through, Nextcloud admin UI doesn't show up. Everything looks like Oscar.
3. **One mobile app** — React Native wrapper around Oscar's existing components. Same APIs, same auth, same offline story.
4. **One deployment** — one VPS, one vhost, one TLS cert, one PB row, one backup job.
5. **One identity** — "Oscar" is the product. "FreshCloud" is the marketing name for the groupware layer. Same codebase, same MIT license.
6. **One set of credentials** — PocketBase stores per-user IMAP/SMTP/CalDAV/WebDAV creds, encrypted. One credential surface for everything.
7. **One mobile story** — when the Android app caches, it caches the whole Oscar experience, not just some surfaces.
8. **One offline story** — TanStack DB or similar, syncs when online, works when offline.

## What this kills

- ❌ **Iframe plan** (was always wrong — couldn't do per-user accounts cleanly)
- ❌ **FreshCloud as a separate product** (over-scoped, would have been a "kit of apps")
- ❌ **Two apps glued together** (Caddy vhost juggling, double TLS, double auth)
- ❌ **7 separate `freshcloud-*` repos** as user-facing apps (we have ONE app, with multiple surfaces)
- ❌ **Nextcloud as a platform with our UI on top** (we already have a platform — Oscar)

## What this keeps

- ✅ `avidtech6/freshmail` as the **library** (786 files of MIT-licensed SnappyMail code, vendored into Oscar)
- ✅ `avidtech6/oscar-platform` as the **app** (everything user-facing lives here)
- ✅ PocketBase for storage, per-user isolation, and credential vault
- ✅ The pocketbase `deployments` row for the Oscar instance
- ✅ The auth shim (PB → portal → Oscar) — already built, works for the new architecture
- ✅ The Section 5 dance we did for SnappyMail — `avidtech6/freshmail` is already MIT
- ✅ `pact/` for canonical doctrine, codex, decisions, plans

## Audience model

Three real audiences, one app, different deployments:

| Audience | Who | What they use | How deployed |
|---|---|---|---|
| **Mark's deployment** | Mark Chester (tree surveyor) + wife | Email, calendar, contacts, files, projects, reports, AI | VPS-hosted Oscar, FreshCloud enabled for Mark + wife as separate users |
| **G's deployment** | You (operator) | Email, calendar, contacts, files, projects, notes, AI | VPS-hosted Oscar (could be same VPS or separate), FreshCloud enabled |
| **School's deployment** | 10-50 students/teachers | Email, calendar, contacts, files, documents | VPS-hosted Oscar (or school-hosted), FreshCloud enabled for whole school |

Same codebase. Same MIT license. Same operator panel. Different `/config.json` per deployment.

## The four phases (sketched, not committed)

### Phase 1: FreshCloud Mail MVP inside Oscar (~2-3 weeks)

**Goal**: Mark + his wife have working email inside Oscar, no iframe, no second app

- Vendor `avidtech6/freshmail` (786 files of MIT SnappyMail source) into Oscar's PHP backend
- Build `/api/email/*` REST endpoints:
  - `POST /api/email/accounts` — add IMAP/SMTP account
  - `GET /api/email/accounts` — list user's accounts
  - `GET /api/email/folders?account_id=X` — list folders
  - `GET /api/email/messages?account_id=X&folder=Y&limit=50` — list messages
  - `GET /api/email/messages/:id` — get single message
  - `POST /api/email/send` — send via SMTP
  - `PATCH /api/email/messages/:id` — mark read, flag, move
- Per-user IMAP/SMTP creds in PocketBase, encrypted
- Build React `<EmailPane />` component inside Oscar
- v1: Gmail via app password (no OAuth yet), regular IMAP/SMTP servers
- No new domain, no new vhost, no new TLS cert — all in Oscar

**Deliverable**: Mark and his wife log into Oscar, see their email, send and receive, no SnappyMail UI leaks through.

### Phase 2: FreshCloud Calendar + Contacts + Files (~3-4 weeks)

**Goal**: Mark has working calendar, contacts, files inside Oscar

- Same pattern as Phase 1, but for CalDAV/CardDAV/WebDAV
- CalDAV for calendar (read, write, sync)
- CardDAV for contacts
- WebDAV for files (read, write, upload, download)
- React components: `<CalendarPane />`, `<ContactsPane />`, `<FilesPane />`
- All inside Oscar's domain

**Deliverable**: Mark uses Oscar for email + calendar + contacts + files. He doesn't open a separate app for any of it.

### Phase 3: OAuth + mobile + polish (~2-3 months)

**Goal**: OAuth login for Gmail/Outlook, Android app, offline cache

- Gmail OAuth (the bits Nextcloud Mail has built in, we have to build — but Mark + his wife use this)
- Microsoft OAuth for Outlook
- React Native Oscar mobile app (wraps the existing React components)
- Offline cache for email (using a library like `react-native-mail-engine` for the native side)
- Push notifications via Firebase Cloud Messaging

**Deliverable**: Mark installs the Oscar app on his phone, sees his email/calendar/files, can read offline.

### Phase 4: Document editing + sovereign AI (~1-2 months)

**Goal**: Document editing in-browser, optional offline AI

- Collabora Online (MPL 2.0, vendored as Docker image) for document editing
- LocalAI (MIT, vendored as Docker image) for sovereign offline AI — **optional**, default uses MiniMax/Z.AI
- React component for document editor: `<DocEditor />`
- React component for AI assistant: extended `<AskUnit />` with FreshCloud context

**Deliverable**: Mark edits Word/Excel docs in Oscar. AI features work offline if operator chooses.

**Total timeline**: 4-6 weeks for Phases 1-2 (Mark working with full groupware), 2-3 months for Phase 3 (mobile), longer for Phase 4 (documents + AI).

## The technical shape

```
┌─────────────────────────────────────────────────────┐
│  Oscar Platform (oscar.freshvibeapps.com)            │
│  ─────────────────────────────────────────────────  │
│  React SPA — the front door                          │
│                                                     │
│  Surfaces:                                          │
│    /          — work surface (AskUnit, projects)     │
│    /notes     — note-taking                           │
│    /reports   — report drafts                         │
│    /mail      — FreshCloud Mail (Phase 1)            │
│    /calendar  — FreshCloud Calendar (Phase 2)        │
│    /contacts  — FreshCloud Contacts (Phase 2)        │
│    /files     — FreshCloud Files (Phase 2)           │
│    /docs      — FreshCloud + Collabora (Phase 4)     │
│    /settings  — all credentials, accounts, prefs     │
│                                                     │
│  APIs:                                              │
│    /api/email/*     — IMAP/SMTP bridge (Phase 1)     │
│    /api/caldav/*    — CalDAV proxy (Phase 2)         │
│    /api/carddav/*   — CardDAV proxy (Phase 2)        │
│    /api/webdav/*    — WebDAV proxy (Phase 2)         │
│    /api/ai/*        — LLM bridge (existing)          │
│    /api/auth/*      — PocketBase auth (existing)     │
│                                                     │
│  Auth: PB → portal → app (existing bridge)          │
│  Data: PocketBase (existing) + per-user creds       │
│  Storage: VPS filesystem (existing)                  │
└─────────────────────────────────────────────────────┘

Backend services (same VPS, behind nginx):
  - PHP-FPM pool for Oscar SPA (existing)
  - PHP-FPM pool for FreshCloud backend (Phase 1+)
  - Collabora Online Docker (Phase 4, optional)
  - LocalAI Docker (Phase 4, optional)
  - PocketBase (existing)
  - LLM bridge (existing, calls MiniMax/Z.AI)
```

## What changed in our thinking (the journey)

Earlier in this conversation, the path was:
- "Iframe SnappyMail into Oscar" (rejected — wrong architecture)
- "Use our SnappyMail fork as a separate product" (rejected — over-scoped)
- "Vendor Nextcloud + lean apps, do the Section 5 dance for each, deploy as `freshcloud-*` repos" (rejected — too many separate repos, too many deployment surfaces)
- "Use Nextcloud's AI as a reference, build our own MIT" (parked for later)
- **"FreshCloud is Oscar's groupware layer" (LOCKED)** — current framing

The locked framing is: **build a real, working groupware inside Oscar**. Don't bolt on existing products. Don't iframe them. Don't glue them. Make them part of Oscar.

## Open questions (not yet answered)

1. **OAuth library choice** — do we vendor Nextcloud's OAuth code (AGPLv3, Section 5 dance) or use a smaller MIT lib like `league/oauth2-client`?
2. **CalDAV/CardDAV library** — Nextcloud's DAV code (AGPLv3) is the gold standard, but a smaller MIT lib like `sabre/dav` might suffice.
3. **Collabora Online as Docker image or as a system install** — Docker is easier to vendor, but adds a Docker dependency.
4. **Mobile app tech stack** — React Native (matches existing React) or Capacitor (webview wrapper, easier to maintain).
5. **Phase 1 priority confirmation** — vendor freshmail first (proves the pattern), or vendor a smaller CalDAV lib first (proves a different pattern)?

## What I'm NOT proposing (deliberately)

- ❌ Building a multi-tenant email service that 100 clients share — we host one Oscar per audience, not a SaaS
- ❌ Replacing PocketBase with Nextcloud's database — PB works for our scale and we own the schema
- ❌ Forking the entire Nextcloud codebase — we only need the IMAP/SMTP/CalDAV libraries, not the full server
- ❌ A separate `freshcloud-server` repo as a vendored monolith — we vendor just the libraries we need
- ❌ Building our own LLM from scratch — we use open-weight models + MIT runtimes (LocalAI when needed)
- ❌ Trying to be a Nextcloud replacement — Oscar is the product, FreshCloud is a layer

## Why this doc exists

This conversation thread (2026-07-18 01:24-01:47 UTC) meandered through:
- SnappyMail vs Nextcloud vs Cypht vs SOGo vs Roundcube
- AGPLv3 → MIT relicensing
- Multi-tenant vs single-tenant architecture
- Iframe vs native vs hybrid
- Where the email backend should live
- The "what if we make this an Android app" question
- The "let's think bigger" realization

That meandering is valuable context but hard to read linearly. This doc captures the final framing, the reasoning, the open questions, and the phases — so any future Mavis session (or future G, or future Mark) can pick it up without re-deriving.

## Related docs

- `pact/dev-docs/` (this folder) — design explorations in progress
- `pact/plans/` — actionable implementation plans (when this becomes a plan, it moves here)
- `pact/decisions/` — constitutional DO-* records (decisions made, not in-progress thinking)
- `pact/codex/email.codex.md` (to be written) — module-level pact for the email surface
- `/workspace/.mavis/plans/2026-07-18/nextcloud-kit-of-parts.md` — the EARLIER plan (mostly superseded, kept for history)
- `/workspace/oscar-platform/pact/plans/future-areas-2026-07-17.md` — parked features
- Memory: "Comms module killed" — prior art on what NOT to do (a separate comms product that didn't earn its place)

## Status

**OPERATOR-LOCKED 2026-07-18 01:51 UTC** (see freshcloud-mail-phase1.md for the build log).

- ✅ "Yes, FreshCloud is Oscar's groupware layer" (the framing) — confirmed
- ✅ "Start with Phase 1 (Mail inside Oscar)" (the priority) — in progress, **architecture proven v0.1.0-test**
- ✅ "`avidtech6/freshmail` becomes the library" (the asset reframe) — done, symlinked into Oscar's PHP backend
- ✅ "All FreshCloud repos use the `freshcloud-*` naming convention" — `avidtech6/freshcloud-mail` created, MIT, private, 10 files (see freshcloud-mail-deploy.md for the deploy protocol)

### Phase 1 build state (2026-07-18)

- PHP-FPM routing through Oscar's vhost: **PROVEN** — `/api/email/{,health,accounts,test-imap}` all return JSON
- MailSo library reachable: **PROVEN** — symlinked from freshmail repo
- Real IMAP connect: **PARTIAL** — `test-imap` reaches MailSo but fails on `RainLoop\API not found` (expected, SnappyMail runtime dep)
- PB schema for accounts: **NOT YET**
- Per-user auth: **STUB** (returns `admin@freshvibeapps.local`)
- Real account CRUD: **NOT YET**
- React `<EmailPane />`: **NOT YET** (Phase 1.2)

See `freshcloud-mail-phase1.md` for the full build log + Phase 1.1 next steps.
