feat: Phase 3+4 — security hardening + polish + offline + Electron push

Phase 3 (security):
- P3.1: Feature gate server-side enforcement (403 on disabled features)
- P3.2: Unified auth error interceptor (401→logout)
- P3.3: Store-level state isolation via StoreSnapshot contract
  (added message-list-tabs + task stores to snapshot/restore cycle)
- P3.4: Push event bus extraction — email-store no longer imports
  calendar/contact/filter/file stores directly
- P1.3: Auth localStorage AES-GCM encryption via custom Zustand adapter

Phase 4 (polish):
- P4.1: Offline write queue — pending operations in localStorage,
  auto-retry on reconnect, offline-queue-indicator banner
- P4.2: Identity spoofing — fromOverrideEmail domain validation
- P4.3: WebSocket push for Electron via main-process IPC bridge
  (ws package with Authorization headers)
This commit is contained in:
Bernd Rodler
2026-08-07 22:10:26 +02:00
parent 0ac429fe36
commit cfdd091d22
29 changed files with 1068 additions and 93 deletions
+5
View File
@@ -22,6 +22,7 @@ import {
} from '@/lib/mail-index/reindex';
import { CONTENT_TYPES, isContentType, type ContentType } from '@/lib/mail-index/store';
import { JmapIndexError } from '@/lib/mail-index/jmap';
import { isFeatureEnabledServer } from '@/lib/admin/feature-gate';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
@@ -40,6 +41,10 @@ function parseIdMap(raw: unknown): Partial<Record<ContentType, string[]>> | unde
}
export async function POST(request: NextRequest) {
if (!isFeatureEnabledServer('aiAssistantEnabled')) {
return NextResponse.json({ error: 'Feature disabled' }, { status: 403 });
}
if (!getStoreDir()) {
return new NextResponse(null, { status: 404 });
}