# Wave 0 — Feature Inventory **Run:** 2026-08-07-v1.7.8-baseline **Skill:** VNCmailgraph (adapted for Next.js/Zustand) **Commit:** d8bebb531f86cab3507aed2113e8d0e6a03c1aa8 **Version:** vnc-v0.3.0-94-gd8bebb53 (VERSION=1.7.8) **Codebase:** ~188K LOC across 745 TS/TSX files (excluding node_modules, .git) **Framework:** Next.js 16 (App Router) + React 19 + Zustand 5 **Backend:** Stalwart Mail Server (JMAP protocol) **Targets:** Web (PWA), Electron Desktop, Native (planned via Capacitor/RN) --- ## Method Adaptation The original VNCmailgraph methodology assumes Angular + NgRx + `isCordova`/`isElectron` gates. This codebase uses: - **Next.js 16 App Router** (not Angular) — routes defined via file-system routing - **Zustand** (not NgRx) — stores in `stores/*.ts`, accessed via hooks - **`isElectronShell()`** (not `isCordova`/`isElectron`) — platform detection via `window.vnc` - **No `zimbra-features.ts`** — feature flags are in `lib/admin/types.ts` (`FeatureGates`, `SettingsPolicy`) - **JMAP protocol** (not Zimbra SOAP) — `lib/jmap/client.ts` (7446 lines) The audit method translates cleanly: feature domains = page routes + component trees; shared substrate = stores + lib services; coupling = cross-store imports. --- ## Feature Domains (derived from code) ### F1 — Mail / Email (CORE) - **Routes:** `/app/(main)/[locale]/page.tsx` (3758 lines — main mail client) - **Components:** `components/email/` (24 files): email-list, email-viewer (5102 lines), email-composer (3432 lines), thread-conversation-view, rich-text-editor (TipTap), tag-picker, email-hover-actions, recipient-popover, calendar-invitation-banner, unsubscribe-banner, read-receipt-banner, message-list-tabs - **Store:** `stores/email-store.ts` (4087 lines) — largest store, manages emails, mailboxes, threads, search, tags, push connection, cross-account views - **Protocol:** `lib/jmap/client.ts` (7446 lines) — the JMAP client powering all mail operations - **Sub-features:** Compose/drafts, threading, unified mailbox, cross-account views, search, tags/keywords, attachments, scheduled send, read receipts (MDN), archive modes, virtual scrolling, TNEF extraction, .eml import, print ### F2 — Calendar - **Routes:** `/app/(main)/[locale]/calendar/page.tsx` - **Components:** `components/calendar/` (22 files): month/week/day/agenda views, event-modal (1375 lines), mini-calendar, task-modal, recurrence-editor, ical-import/subscription modals, participant-input - **Store:** `stores/calendar-store.ts` (1289 lines) — calendars, events, multi-account aggregation, recurrence expansion, iMIP, CalDAV - **Sub-features:** Month/week/day/agenda views, drag-to-reschedule, recurring events, iMIP invitations, .ics import, birthday calendar, virtual locations, tasks, CalDAV shared calendars ### F3 — Contacts - **Routes:** `/app/(main)/[locale]/contacts/page.tsx` - **Components:** `components/contacts/` (17 files): contact-list, contact-detail, contact-form, import-dialog, groups - **Store:** `stores/contact-store.ts` (1146 lines) — contact cards, address books, multi-account, vCard import/export - **Sub-features:** JMAP sync (RFC 9553/9610), address books, groups, vCard import/export, trusted senders, autocomplete ### F4 — Files / Briefcase - **Routes:** `/app/(main)/[locale]/files/page.tsx` - **Components:** `components/files/` (10 files): file-browser (2022 lines), folder-tree, upload-area, preview-modal - **Stores:** `stores/file-store.ts` (1050 lines) + `stores/webdav-store.ts` (480 lines) — dual storage backends - **Sub-features:** JMAP FileNode browsing, WebDAV upload with progress, grid/list views, preview, cut/copy/paste, favorites, sharing (RFC 9670) ### F5 — Tasks - **Store:** `stores/task-store.ts` (95 lines) — VTODO CRUD, filter by pending/completed/overdue - **Components:** `components/calendar/task-modal.tsx`, `task-list-view.tsx`, `task-toolbar.tsx` - **Feature gate:** `calendarTasksEnabled` in admin policy ### F6 — Settings / Preferences - **Routes:** `/app/(main)/[locale]/settings/page.tsx` - **Components:** `components/settings/` (33 files) — account, appearance, themes, layout, reading, composing, notification, folder, filter, vacation, identity, template, keyword, calendar, contacts, files, downloads, sidebar-apps, plugins, language, protocol-handler, AI, debug, about - **Store:** `stores/settings-store.ts` (1221 lines) — all user settings with cross-device encrypted sync - **Sub-features:** Theme/density/font, layout preferences, reply/signature behavior, notification preferences, mailto:/webcal: protocol handling, settings sync (AES-256-GCM) ### F7 — Filters / Sieve - **Components:** `components/filters/` (2 files): filter-rule-modal (534 lines), sieve-editor-modal - **Store:** `stores/filter-store.ts` (254 lines) — Sieve script management - **Lib:** `lib/sieve/` (parser + generator) — round-trip for external scripts - **Sub-features:** Visual rule builder, raw Sieve editor, vacation responder, opaque script preservation ### F8 — Templates - **Components:** `components/templates/` (4 files): template-picker, template-form, manager-modal, placeholder-fill - **Store:** `stores/template-store.ts` (153 lines) — CRUD, favorites, import/export - **Feature gate:** `templatesEnabled` ### F9 — Identity / Aliases - **Components:** `components/identity/` (3 files): identity-manager-modal (407 lines), identity-form, sub-address-helper - **Store:** `stores/identity-store.ts` (140 lines) — sender identities, sub-addressing - **Sub-features:** Multiple sender identities per account, sub-addressing (`user+tag@domain`) ### F10 — AI Assistant - **Components:** `components/ai/ai-ask-button.tsx` (264 lines) - **Lib:** `lib/ai/` (9 files + retrieval/): local-client, local-discovery, opencode, entitlement, key-store, retrieval/fusion - **API:** `app/api/ai/` (server/chat, server/models, retrieve, opencode/chat, opencode/models, policy) - **Sub-features:** Local LLM (Ollama), server-hosted AI, BYOK, OpenCode runtime, mail retrieval with RRF fusion, FTS5 search index - **Feature gate:** `aiAssistantEnabled` (default=true) ### F11 — Admin / Management - **Routes:** 14 admin pages (dashboard, settings, branding, auth, password, policy, plugins, themes, marketplace, version, telemetry, logs) - **Lib:** `lib/admin/` (18 files): config-manager, session, password, audit, plugin-registry, plugin-approvals, plugin-signing, bundled-plugins, domain-branding, CSP - **Store:** `stores/admin-tab-store.ts` (42 lines) ### F12 — Plugin System - **Components:** `components/plugins/` (7 files): plugin-slot, iframe-slot, dialog-host, consent-dialog, error-boundary - **Store:** `stores/plugin-store.ts` (596 lines) — lifecycle management - **Lib:** `lib/plugin-sandbox/` (13 files): runtime, host-bridge, host-api, loader, tier, protocol, registry, bundle-integrity, bundle-signing, consent, shortcuts - **Sub-features:** Sandboxed iframe execution, postMessage RPC, tiered permissions (untrusted/privileged), admin approval gates, marketplace, dev-mode loading ### F13 — Pro Multi-Tab Shell - **Routes:** `/app/(main)/[locale]/pro/page.tsx` - **Components:** `components/pro/` (4 files): tab-bar, email-tab-body, compose-tab-body, interface-redirect - **Store:** `stores/pro-tab-store.ts` (576 lines) — multi-tab management, split pane layout ### F14 — Search - **Components:** `components/search/` (2 files): search-chips, advanced-search-panel - **Backend:** `lib/mail-index/` (8 files) — encrypted SQLite/FTS5 index (Electron-only) - **API:** `app/api/offline/search`, `app/api/ai/retrieve` - **Coupling:** Heavily coupled with email-store (search state lives there) ### F15 — Authentication - **Lib:** `lib/auth/` (7 files): crypto, session-cookie, session-secret, verify-jmap-auth, pair-reauth, pairing-store, active-account-slot - **Store:** `stores/auth-store.ts` (2033 lines) — THE hub; manages login, logout, token refresh, multi-account sessions - **Sub-features:** Basic auth, OAuth/OIDC with PKCE, demo mode, device pairing, TOTP 2FA, impersonation (JWT) - **API:** `app/api/auth/` (10 routes) ### F16 — Setup Wizard - **Routes:** `/app/(main)/setup/*` - **Lib:** `lib/setup/` (3 files): session, state, token - **API:** `app/api/setup/` (6 routes) --- ## Shared Substrate ### S1 — State Management (Zustand stores) - 28 store files in `stores/` — Zustand with `persist` middleware - **Central hub:** `auth-store.ts` imports 7 other stores; bootstraps all feature stores after login - **Bidirectional cycle:** `email-store` ↔ `message-list-tabs-store` - **Anti-cycle pattern:** `client-registry.ts` — utility indirection to avoid auth-store cycles - **Clean leaves:** `locale-store`, `policy-store`, `toast-store`, `ui-store` (0 dependencies) ### S2 — JMAP Protocol Layer - `lib/jmap/client.ts` (7446 lines) — the communication backbone for ALL features - `lib/jmap/types.ts` (938 lines) — shared type definitions - `lib/jmap/client-interface.ts` (358 lines) — `IJMAPClient` interface (real + demo implementations) - `lib/jmap/transport-health.ts` — failure counter for offline fallback gating - `lib/jmap/request-limits.ts` — request batching utilities - `lib/jmap/search-utils.ts` — search query building ### S3 — Auth / Session / Multi-Account - `lib/auth/*` — AES-256-GCM cookie encryption, session lifecycle, device pairing - `lib/oauth/*` — OAuth2/OIDC discovery, PKCE, token exchange - `lib/impersonation/*` — JWT platform auth - `lib/stalwart/*` — server-side Stalwart auth context, JMAP passthrough - `stores/account-store.ts` — multi-account registry - `stores/account-security-store.ts` — TOTP 2FA, app passwords, API keys ### S4 — Offline Replica (encrypted delta-sync mail store) - `lib/offline-replica/` (13 files): engine, sync (1122 lines), store (997 lines), apply, jmap, states, read, retention, errors, schema, types - SQLCipher-encrypted SQLite; delta sync via JMAP `/changes` - Two-tier storage (envelope + body); cursor provenance with branded types - **Fallback only** — consulted after live JMAP read fails; online session never sees replica data ### S5 — Local Search Index (encrypted FTS5) - `lib/mail-index/` (8 files): store (534 lines), jmap (388 lines), extract (311 lines), reindex (385 lines), key (203 lines), paths, binding - SQLCipher-encrypted SQLite with FTS5, **Electron/desktop only** - Event-driven (triggered by JMAP push changes via API routes) - Key transport uses inherited fd (pipe), not env var ### S6 — Platform Bridge - `lib/electron-bridge.ts` (55 lines) — `isElectronShell()`, `showElectronNotification()` - `lib/platform-capabilities.ts` (29 lines) — single source of truth for platform feature availability - `lib/web-push.ts` — web push for PWA - `electron/main.ts` (424 lines) — Electron main process (spawns Next.js server) - `electron/preload.ts` (27 lines) — contextBridge, nodeIntegration=false, sandbox=true ### S7 — Plugin Sandbox - `lib/plugin-sandbox/` (13 files) — iframe isolation, postMessage RPC, tier gating - `lib/plugin-types.ts` (1092 lines) — massive type definitions - `lib/plugin-hooks.ts` — hook registration for email/calendar/composer/sidebar slots - `lib/plugin-loader.ts`, `lib/plugin-validator.ts`, `lib/plugin-storage.ts` ### S8 — HTTP Proxy / API Gateway - `proxy.ts` (211 lines) — Next.js middleware: CSP, nonce, setup-state gating, intl routing - `app/api/*` — 24 API endpoint groups (auth, admin, AI, offline, setup, etc.) ### S9 — Security / Sanitization - `lib/security/url-guard.ts` (67 lines) — SSRF prevention, loopback/private-IP blocking - `lib/email-sanitization.ts` — DOMPurify HTML sanitization - `lib/smime-ca/` (5 files) — S/MIME certificate authority (EJBCA + local dev CA) ### S10 — Theme System - `stores/theme-store.ts` (593 lines) — light/dark/system, custom theme installation - `lib/theme-compiler.ts`, `lib/theme-loader.ts`, `lib/theme-logo.ts` - `lib/builtin-themes.ts` — 8 built-in themes (2 shipping, 6 hidden) - `lib/color-transform.ts` — luminance-based color remapping for dark mode ### S11 — Internationalization - `stores/locale-store.ts` (19 lines) - `i18n/routing.ts` — next-intl configuration - `locales/` — 24 language translations - `lib/jalali-utils.ts` — Persian calendar support ### S12 — Cross-Device Settings Sync - `lib/settings-sync.ts` — encrypted settings sync (AES-256-GCM) ### S13 — Telemetry - `lib/telemetry/` (7 files) — anonymous heartbeat, opt-in, HMAC-hashed logins ### S14 — Version Check - `lib/version-check/` (5 files) — polls version server, daily jittered schedule - `stores/update-store.ts` (118 lines) --- ## Feature Flag Registry (from lib/admin/types.ts) | Flag | Default | Description | |------|---------|-------------| | `pluginsEnabled` | false | Plugin system on/off | | `pluginsUploadEnabled` | true | Allow manual plugin upload | | `requirePluginApproval` | true | Admin must approve plugins | | `themesEnabled` | true | Theme system on/off | | `sidebarAppsEnabled` | true | Sidebar app visibility/order | | `userThemesEnabled` | true | Users can install custom themes | | `settingsExportEnabled` | true | Settings export | | `customKeywordsEnabled` | true | Custom keyword/tag creation | | `templatesEnabled` | true | Email templates | | `calendarEnabled` | true | Calendar feature | | `calendarTasksEnabled` | true | Calendar tasks | | `smimeEnabled` | true | S/MIME | | `externalContentEnabled` | true | External content in emails | | `debugModeEnabled` | true | Debug tools | | `folderIconsEnabled` | true | Custom folder icons | | `hoverActionsConfigEnabled` | true | Hover action configuration | | `filesEnabled` | true | File browser | | `contactsEnabled` | true | Contacts | | `crossAllViewEnabled` | false | Cross-account All Mail | | `crossUnreadViewEnabled` | false | Cross-account Unread | | `crossStarredViewEnabled` | false | Cross-account Starred | | `unifiedCrossAccountEnabled` | false | Cross-account unified inbox | | `aiAssistantEnabled` | true | AI assistant (visible by default — local ships free) | --- ## Dependency / Coupling DAG (Store Layer) ``` auth-store (HUB) ──→ identity-store ├──→ account-store ├──→ calendar-store ├──→ contact-store ├──→ filter-store ├──→ settings-store └──→ vacation-store email-store ──→ calendar-store ├──→ auth-store ├──→ account-store ├──→ settings-store └──→ message-list-tabs-store ←── (BIDIRECTIONAL CYCLE) settings-store ──→ theme-store └──→ locale-store plugin-store ──→ locale-store └──→ policy-store theme-store ──→ policy-store account-security-store ──→ auth-store Standalone (14): file-store, task-store, filter-store, identity-store, account-store, pro-tab-store, ui-store, vacation-store, totp-reauth-store, calendar-notification-store, managed-account-store, update-store, toast-store, admin-tab-store, template-store, webdav-store ``` **Critical coupling paths to audit in Wave 2:** 1. `auth-store` → bootstraps 7 feature stores on login → any bootstrap failure cascades 2. `email-store` ↔ `message-list-tabs-store` — bidirectional cycle 3. `email-store` → `calendar-store` — cross-feature coupling (invitation banners, birthday calendar) 4. `settings-store` → `theme-store` → theme injection affects ALL components 5. JMAP client (`lib/jmap/client.ts`) → used by ALL feature stores via `client-registry` --- ## Platform Parity Surface | Feature | Web (PWA) | Electron Desktop | Native (planned) | |---------|-----------|------------------|------------------| | Mail | Full | Full | Full (planned) | | Calendar | Full | Full | Full (planned) | | Contacts | Full | Full | Full (planned) | | Files | Full | Full | Full (planned) | | Local Search Index | ❌ | SQLCipher FTS5 | ❌ (planned) | | Offline Replica | ❌ | SQLCipher SQLite | ❌ (planned) | | Native Notifications | Web Push | Electron Notification | Native (planned) | | AI Local LLM | Browser CORS | No CORS (loopback) | Native (planned) | | S/MIME | Full | Full | Full (planned) |