---
trigger: always_on
---

## Architecture

```
src/noteflow/
├── domain/           # Entities + ports (see Domain Package Structure below)
├── application/      # Use-cases/services (Meeting, Recovery, Export, Summarization, Trigger, Webhook, Calendar, Retention, NER)
├── infrastructure/   # Implementations
│   ├── audio/        # sounddevice capture, ring buffer, VU levels, playback, buffered writer
│   ├── asr/          # faster-whisper engine, VAD segmenter, streaming
│   ├── diarization/  # Speaker diarization (streaming: diart, offline: pyannote.audio)
│   ├── summarization/# Multi-provider summarization (CloudProvider, OllamaProvider) + citation verification
│   ├── triggers/     # Auto-start signal providers (calendar, audio activity, foreground app)
│   ├── persistence/  # SQLAlchemy + asyncpg + pgvector, Alembic migrations
│   ├── security/     # keyring keystore, AES-GCM encryption
│   ├── crypto/       # Cryptographic utilities
│   ├── export/       # Markdown/HTML/PDF export
│   ├── webhooks/     # Webhook executor with retry logic and HMAC signing
│   ├── converters/   # ORM ↔ domain entity converters (including webhook, NER, calendar, integration)
│   ├── calendar/     # OAuth manager, Google/Outlook calendar adapters
│   ├── ner/          # Named entity recognition engine (spaCy)
│   ├── observability/# OpenTelemetry tracing, usage event tracking
│   ├── metrics/      # Metric collection utilities
│   ├── logging/      # Log buffer and utilities
│   └── platform/     # Platform-specific code
├── grpc/             # Proto definitions, server, client, meeting store, modular mixins
├── cli/              # CLI tools (retention management, model commands)
└── config/           # Pydantic settings (NOTEFLOW_ env vars) + feature flags
```

Frontend (Tauri + React) lives outside the Python package:

```
client/
├── src/              # React UI, state, and view components
├── src-tauri/        # Rust/Tauri shell, IPC commands, gRPC client
├── e2e/              # Playwright tests
├── package.json      # Vite + test/lint scripts
└── vite.config.ts    # Vite configuration
```

**Key patterns:**
- Hexagonal architecture: domain → application → infrastructure
- Repository pattern with Unit of Work (`SQLAlchemyUnitOfWork`)
- gRPC bidirectional streaming for audio → transcript flow
- Protocol-based DI (see `domain/ports/` and infrastructure `protocols.py` files)
- Modular gRPC mixins for separation of concerns (see below)

### Domain Package Structure

```
domain/
├── entities/         # Core domain entities
│   ├── meeting.py    # Meeting, MeetingId, MeetingState
│   ├── segment.py    # Segment, WordTiming
│   ├── summary.py    # Summary, KeyPoint, ActionItem
│   ├── annotation.py # Annotation
│   ├── named_entity.py # NamedEntity for NER results
│   └── integration.py# Integration, IntegrationType, IntegrationStatus
├── identity/         # User/workspace identity (Sprint 16)
│   ├── roles.py      # WorkspaceRole enum with permission checks
│   ├── context.py    # UserContext, WorkspaceContext, ProjectContext, OperationContext
│   └── entities.py   # User, Workspace, WorkspaceMembership domain entities
├── webhooks/         # Webhook domain
│   ├── events.py     # WebhookEventType, WebhookConfig, WebhookDelivery, payload classes
│   └── constants.py  # Webhook-related constants
├── triggers/         # Trigger detection domain
│   ├── entities.py   # Trigger, TriggerAction, TriggerSignal
│   └── ports.py      # TriggerProvider protocol
├── summarization/    # Summarization domain
│   └── ports.py      # SummarizationProvider protocol
├── ports/            # Repository protocols
│   ├── repositories/ # Organized by concern
│   │   ├── transcript.py  # MeetingRepository, SegmentRepository, SummaryRepository
│   │   ├── asset.py       # AssetRepository for file management
│   │   ├── background.py  # DiarizationJobRepository, EntityRepository
│   │   ├── external.py    # WebhookRepository, IntegrationRepository, PreferencesRepository
│   │   └── identity.py    # UserRepository, WorkspaceRepository protocols
│   ├── unit_of_work.py    # UnitOfWork protocol with supports_* capability checks
│   ├── diarization.py     # DiarizationEngine protocol
│   ├── ner.py             # NEREngine protocol
│   └── calendar.py        # CalendarProvider protocol
├── utils/            # Domain utilities
│   └── time.py       # utc_now() helper
├── errors.py         # Domain-specific exceptions
└── value_objects.py  # Shared value objects
```

## gRPC Mixin Architecture

The gRPC server uses modular mixins for maintainability:

```
grpc/_mixins/
├── streaming/        # ASR streaming (package)
│   ├── _mixin.py     # Main StreamingMixin class
│   ├── _session.py   # Session management
│   ├── _asr.py       # ASR processing
│   ├── _processing.py# Audio processing pipeline
│   ├── _partials.py  # Partial transcript handling
│   ├── _cleanup.py   # Resource cleanup
│   └── _types.py     # Type definitions
├── diarization/      # Speaker diarization (package)
│   ├── _mixin.py     # Main DiarizationMixin class
│   ├── _jobs.py      # Background job management
│   ├── _refinement.py# Offline refinement
│   ├── _streaming.py # Real-time diarization
│   ├── _speaker.py   # Speaker assignment
│   ├── _status.py    # Job status tracking
│   └── _types.py     # Type definitions
├── summarization.py  # Summary generation (separates LLM inference from DB transactions)
├── meeting.py        # Meeting lifecycle (create, get, list, delete, stop)
├── annotation.py     # Segment annotations CRUD
├── export.py         # Markdown/HTML/PDF document export
├── entities.py       # Named entity extraction operations
├── calendar.py       # Calendar sync operations
├── webhooks.py       # Webhook management operations
├── preferences.py    # User preferences operations
├── observability.py  # Usage tracking, metrics operations
├── sync.py           # State synchronization operations
├── diarization_job.py# Diarization job status/management
├── converters.py     # Protobuf ↔ domain entity converters
├── errors.py         # gRPC error helpers (abort_not_found, abort_invalid_argument)
├── protocols.py      # ServicerHost protocol for mixin composition
└── _audio_helpers.py # Audio utility functions

grpc/interceptors/    # gRPC server interceptors (Sprint 16)
└── identity.py       # Identity context propagation (request_id, user_id, workspace_id)
```

Client-side mixins for the Python gRPC client:

```
grpc/_client_mixins/
├── streaming.py      # Client streaming operations
├── meeting.py        # Meeting CRUD operations
├── diarization.py    # Diarization requests
├── export.py         # Export requests
├── annotation.py     # Annotation operations
├── converters.py     # Response converters
└── protocols.py      # ClientHost protocol
```

Each mixin operates on `ServicerHost` protocol, enabling clean composition in `NoteFlowServicer`.

### Service Injection Pattern

Services are injected through a three-tier pattern:
1. **ServicerHost Protocol** (`protocols.py`) — declares required service attributes
2. **NoteFlowServicer** (`service.py`) — accepts services via `__init__` and stores as instance attributes
3. **NoteFlowServer** (`server.py`) — creates/initializes services and passes to servicer

Example: `_webhook_service`, `_summarization_service`, `_ner_service` all follow this pattern.

## Client Architecture (Tauri + React)

```
client/src/
├── api/              # API layer with adapters and connection management
│   ├── tauri-adapter.ts    # Main Tauri IPC adapter
│   ├── mock-adapter.ts     # Mock adapter for testing
│   ├── cached-adapter.ts   # Caching layer
│   ├── connection-state.ts # Connection state machine
│   ├── reconnection.ts     # Auto-reconnection logic
│   ├── interface.ts        # Adapter interface definition
│   └── types/              # API type definitions
├── hooks/            # Custom React hooks
│   ├── use-diarization.ts  # Speaker diarization state
│   ├── use-cloud-consent.ts# Cloud provider consent
│   ├── use-webhooks.ts     # Webhook management
│   ├── use-oauth-flow.ts   # OAuth authentication
│   ├── use-calendar-sync.ts# Calendar synchronization
│   ├── use-entity-extraction.ts # NER operations
│   └── ...                 # Additional hooks
├── contexts/         # React contexts
│   └── connection-context.tsx # gRPC connection context
├── components/       # React components
│   ├── ui/           # Reusable UI components (shadcn/ui)
│   ├── recording/    # Recording-specific components
│   ├── settings/     # Settings panel components
│   └── analytics/    # Analytics visualizations
├── pages/            # Route pages
├── lib/              # Utilities
│   ├── tauri-helpers.ts    # Tauri utility functions
│   ├── tauri-events.ts     # Tauri event handling
│   ├── cache/              # Client-side caching
│   ├── config/             # Configuration management
│   └── ...                 # Format, crypto, utils
└── types/            # Shared TypeScript types
```

Rust/Tauri backend:

```
client/src-tauri/src/
├── commands/         # Tauri IPC command handlers
│   ├── recording/    # Recording commands (capture, device, audio)
│   ├── triggers/     # Trigger detection commands
│   ├── meeting.rs    # Meeting CRUD
│   ├── diarization.rs# Diarization operations
│   ├── calendar.rs   # Calendar sync
│   ├── webhooks.rs   # Webhook management
│   └── ...           # Export, annotation, preferences, etc.
├── grpc/             # gRPC client
│   ├── client/       # Client implementations by domain
│   └── types/        # Rust type definitions
├── state/            # Runtime state management
│   ├── app_state.rs  # Main application state
│   ├── preferences.rs# User preferences
│   ├── playback.rs   # Audio playback state
│   └── types.rs      # State type definitions
├── audio/            # Audio capture and playback
├── cache/            # Memory caching
├── crypto/           # Cryptographic operations
├── events/           # Tauri event emission
├── triggers/         # Trigger detection
├── main.rs           # Application entry point
└── lib.rs            # Library exports
```