CRITICAL fixes: - C1: Error swallowing - throw TransportError on network failure in getEmails/searchEmails - C2: Recurrence expansion ID delimiter changed from ':' to '::occurrence::' - C3: Cross-account calendar event UID dedup after multi-account aggregation - C4: Admin session token revocation via JTI blacklist on logout - C6: FTS5 schema-drop - add warning log for automatic reindex trigger - C7: Settings lock - gate updateSetting() with isSettingLocked() check - C8: Offline push pause - add offline event handler that closes push transports HIGH fixes: - H1: Push handler - add ContactCard and FileNode branches - H2: WS fallback - await state snapshot before reconcileAfterWebSocketFallback - H3: Auth rate limiting - add checkUserAuthRateLimit to session and token routes - H4: OAuth logs - strip access_token from error log context - H7: Template XSS - apply DOMPurify to HTML template body on import - H8: Secure cookie - derive from x-forwarded-proto, not NODE_ENV - H9: bcrypt fix - remove bcrypt prefixes from isHashed() so scrypt-only - H13: calendarTasksEnabled - apply admin gate at runtime in calendar page - H14: Task mutations - add try/catch error handling to update/delete/toggle - H18: autoSelectReplyIdentity default changed from false to true Deferred: P1.3 (C5 auth localStorage encryption) - requires custom Zustand persist adapter.
6.9 KiB
Wave 0 — Execution Graph
Run: 2026-08-07-v1.7.8-baseline
Skill: VNCmailgraph
Commit: d8bebb531f
DAG Structure
The graph decomposes the audit into 3 waves:
Wave 0 (DONE) — Inventory + Dependency Map
- Output:
inventory.md+ thisgraph.md - Cost: ~minimal (code exploration, no heavy AI)
Wave 1 — Per-Feature Audits (16 nodes)
Each node audits ONE feature domain against the 6-lens set (Correctness, Data-Integrity, Cross-Feature Coupling, Security, Performance, Platform-Parity). Nodes are independent (can fan out in parallel) — no feature audit reads another feature's output.
Wave 2 — Substrate Synergetic Failure Hunt (8 nodes)
After Wave 1 completes, these nodes hunt failures that SPAN features through shared substrate: store-coupling, offline/storage, sync+push, platform-parity, auth/session/entitlement, doc cross-check, cross-feature synthesis, completeness critic.
Wave 1 Node Assignments (16 nodes, fully parallelizable)
| ID | Feature | Source Roots | Key Files | Estimated Complexity |
|---|---|---|---|---|
| N01 | Mail/Email | app/(main)/[locale]/page.tsx, components/email/, stores/email-store.ts |
email-viewer (5102L), email-composer (3432L), email-list, rich-text-editor, JMAP client (7446L) | VERY HIGH |
| N02 | Calendar | app/(main)/[locale]/calendar/, components/calendar/, stores/calendar-store.ts |
event-modal (1375L), month/week/day views, recurrence-expansion | HIGH |
| N03 | Contacts | app/(main)/[locale]/contacts/, components/contacts/, stores/contact-store.ts |
contact-list (615L), contact-detail (625L), vCard import/export | MEDIUM |
| N04 | Files | app/(main)/[locale]/files/, components/files/, stores/file-store.ts |
file-browser (2022L), WebDAV client, dual storage | MEDIUM |
| N05 | Tasks | stores/task-store.ts, components/calendar/task-*.tsx |
Small feature (95L store) | LOW |
| N06 | Settings | app/(main)/[locale]/settings/, components/settings/, stores/settings-store.ts |
33 settings components, settings-sync | HIGH |
| N07 | Filters/Sieve | components/filters/, stores/filter-store.ts, lib/sieve/ |
filter-rule-modal (534L), parser (866L), generator | MEDIUM |
| N08 | Templates | components/templates/, stores/template-store.ts |
Small feature (153L store) | LOW |
| N09 | Identity/Aliases | components/identity/, stores/identity-store.ts |
identity-manager-modal (407L) | LOW |
| N10 | AI Assistant | components/ai/, lib/ai/, app/api/ai/ |
local-client (422L), opencode (164L), retrieval/fusion, local-discovery | MEDIUM |
| N11 | Admin | app/(main)/admin/*, lib/admin/, stores/admin-tab-store.ts |
18 lib files, 14 pages, config-manager, audit, plugin-registry | HIGH |
| N12 | Plugin System | components/plugins/, stores/plugin-store.ts, lib/plugin-sandbox/ |
13 sandbox files, host-api (933L), runtime (636L), types (1092L) | VERY HIGH |
| N13 | Pro Shell | app/(main)/[locale]/pro/, components/pro/, stores/pro-tab-store.ts |
tab-bar, email/compose tab bodies | LOW |
| N14 | Search | components/search/, lib/mail-index/, stores/email-store.ts (search state) |
FTS5 index (Electron-only), search-chips, advanced-search-panel | MEDIUM |
| N15 | Authentication | lib/auth/, lib/oauth/, stores/auth-store.ts |
auth-store (2033L), crypto, OIDC, pairing, impersonation | HIGH |
| N16 | Setup Wizard | app/(main)/setup/*, lib/setup/ |
session, state, token | LOW |
Wave 2 Node Assignments (8 nodes, partially parallelizable)
| ID | Substrate Concern | Scope | Depends On |
|---|---|---|---|
| N20 | Store-Coupling & Cycles | Cross-store dependency analysis: auth-store hub, email↔tabs cycle, client-registry anti-cycle | N01–N16 |
| N21 | Offline / Storage | lib/offline-replica/ + lib/mail-index/ + RxDB evaluation (§D) |
N01, N04, N10, N14 |
| N22 | Sync + Push + Background | JMAP push, web push (PWA), Electron notifications, offline queue replay, connectivity | N01, N02, N06 |
| N23 | Platform Parity | Electron vs PWA vs Native gaps: isElectronShell() gate spread, local index, offline replica, notifications |
N01–N16 |
| N24 | Auth / Session / Entitlement | Token lifecycle, multi-account isolation, feature-gate enforcement, sharing/delegation auth | N15, N11 |
| N25 | Doc Cross-Check | FEATURES.md vs actual code vs policy feature gates | N01–N16 |
| N26 | Cross-Feature Synthesis | Combines Wave 1 coupling points + Wave 2 substrate findings → cross-feature failures | N01–N25 |
| N27 | Completeness Critic | "What feature, modality, or shared path was NOT covered?" + Fresh-context verify of all CRITICAL/HIGH | N01–N26 |
Calibration Plan
Before fanning out all 16 Wave 1 nodes, calibrate on 2 representative nodes:
- N05 (Tasks) — smallest feature (95 lines), low complexity → calibrate per-node cost lower bound
- N15 (Authentication) — high complexity (2033 lines), the central hub importing 7 stores → calibrate per-node cost upper bound
After calibration, price the full Wave 1 fan-out and report against the AI-cost standing rule.
The 6-Lens Set (applied to every Wave 1 node)
- Correctness / Functioning — trace real code paths for core verbs; do they work as written? error/offline handling?
- Data-Integrity — optimistic UI vs persistence; store↔DB consistency; retention/GC; crash-recovery
- Cross-Feature Coupling — enumerate shared store slices + services touched; each is a candidate synergetic-failure surface
- Security — XSS (email-body → DOM → Electron RCE path), entitlement/permission guards, token/credential logging, sharing authorization
- Performance — virtual scrolling, zoneless CD (Next.js/React: missing memo/useCallback on large lists), worker RPC cost
- Platform-Parity —
isElectronShell()branches, Web Push vs Electron Notification, local index availability, offline replica availability
Finding Template (all nodes)
### [CRITICAL|HIGH|MEDIUM|LOW] Short title
- Category: <feature / substrate / type>
- Location: path/file:line
- Evidence: short quoted snippet or precise description
- Impact: concrete failure scenario (inputs → wrong behavior); cross-feature if applicable
- Recommendation: correct approach
- Confidence: measured | reasoned-not-measured
Key Codebase Anchors
- No secrets in reports (§B.0.2) — redact all keys, tokens, secrets
rglandmine — usegrep -REn/ Read, neverrg(mangleselectron→n)- Cursor provenance (
lib/offline-replica/states.ts) — brandedChangesState/SnapshotState - Deploy policy — dev first, never prod-direct
- AI-cost rule — ≥30% above baseline → report immediately
- Security anchors — DOMPurify sanitization, CSP with per-request nonce, SSRF guard, contextIsolation/sandbox for Electron, plugin bundle integrity + signing