- Revised AGENTS.md to provide comprehensive guidance for AI coding assistants, including project overview, architecture, and development commands. - Enhanced CLAUDE.md by adding the `auth` directory to the infrastructure section, clarifying the project's structure and components. - Improved formatting and organization of both documentation files for better readability and usability.
30 KiB
AGENTS.md
This file provides guidance to AI coding assistants (Cursor, Copilot, Codex, etc.) when working with code in this repository.
Project Overview
NoteFlow is an intelligent meeting notetaker: local-first audio capture + navigable recall + evidence-linked summaries. It is a client-server system built around a gRPC API for bidirectional audio streaming and transcription. The repository includes:
- Python backend (
src/noteflow/) — gRPC server, domain logic, infrastructure adapters - Tauri + React desktop client (
client/) — Rust for IPC, React UI (Vite)
The gRPC schema is the shared contract between backend and client; keep proto changes in sync across Python, Rust, and TypeScript.
Quick Orientation
| Entry Point | Description |
|---|---|
python -m noteflow.grpc.server |
Backend server (src/noteflow/grpc/server/__main__.py) |
cd client && npm run dev |
Web UI (Vite) |
cd client && npm run tauri dev |
Desktop Tauri dev (requires Rust toolchain) |
src/noteflow/grpc/proto/noteflow.proto |
Protobuf schema |
client/src/api/tauri-adapter.ts |
TypeScript → Rust IPC bridge |
client/src-tauri/src/commands/ |
Rust Tauri command handlers |
Build and Development Commands
# Install (editable with dev dependencies)
python -m pip install -e ".[dev]"
# Run gRPC server
python -m noteflow.grpc.server --help
# Run Tauri + React client UI
cd client && npm install && npm run dev
cd client && npm run tauri dev # Desktop (requires Rust)
# Tests
pytest # Full suite
pytest -m "not integration" # Skip external-service tests
pytest tests/domain/ # Run specific test directory
pytest -k "test_segment" # Run by pattern
# Docker (hot-reload enabled)
docker compose up -d postgres # PostgreSQL with pgvector
python scripts/dev_watch_server.py # Auto-reload server
Forbidden Docker Operations (without explicit permission)
docker compose build/up/down/restartdocker stop/docker kill- Any command that would interrupt the hot-reload server
Quality Commands (Makefile)
Always use Makefile targets instead of running tools directly.
Primary Quality Commands
make quality # Run ALL quality checks (TS + Rust + Python)
make quality-py # Python: lint + type-check + test-quality
make quality-ts # TypeScript: type-check + lint + test-quality
make quality-rs # Rust: clippy + lint
Python Quality
make lint-py # Basedpyright lint → .hygeine/basedpyright.lint.json
make type-check-py # Basedpyright strict mode
make test-quality-py # pytest tests/quality/
make lint-fix-py # Auto-fix Ruff + Sourcery issues
TypeScript Quality
make type-check # tsc --noEmit
make lint # Biome linter → .hygeine/biome.json
make lint-fix # Auto-fix Biome issues
make test-quality # Vitest quality tests
Rust Quality
make clippy # Clippy linter → .hygeine/clippy.json
make lint-rs # Code quality script → .hygeine/rust_code_quality.txt
make fmt-rs # Format with rustfmt
make fmt-check-rs # Check rustfmt formatting
Formatting
make fmt # Format all code (Biome + rustfmt)
make fmt-check # Check all formatting
E2E Tests
make e2e # Playwright tests (requires frontend on :5173)
make e2e-ui # Playwright tests with UI mode
make e2e-grpc # Rust gRPC integration tests
Architecture
src/noteflow/
├── domain/ # Entities, ports, value objects
│ ├── entities/ # Meeting, Segment, Summary, Annotation, NamedEntity, Integration, Project, Processing, SummarizationTemplate
│ ├── identity/ # User, Workspace, WorkspaceMembership, roles, context
│ ├── auth/ # OIDC discovery, claims, constants
│ ├── ports/ # Repository protocols
│ │ ├── repositories/
│ │ │ ├── transcript.py # MeetingRepository, SegmentRepository, SummaryRepository
│ │ │ ├── asset.py # AssetRepository
│ │ │ ├── background.py # DiarizationJobRepository
│ │ │ ├── external/ # WebhookRepository, IntegrationRepository, EntityRepository, UsageRepository
│ │ │ └── identity/ # UserRepository, WorkspaceRepository, ProjectRepository, MembershipRepository, SummarizationTemplateRepository
│ │ ├── unit_of_work.py # UnitOfWork protocol (supports_* capability checks)
│ │ ├── async_context.py # Async context utilities
│ │ ├── diarization.py # DiarizationEngine protocol
│ │ ├── ner.py # NEREngine protocol
│ │ └── calendar.py # CalendarProvider protocol
│ ├── webhooks/ # WebhookEventType, WebhookConfig, WebhookDelivery, payloads
│ ├── triggers/ # Trigger, TriggerAction, TriggerSignal, TriggerProvider
│ ├── summarization/# SummarizationProvider protocol
│ ├── rules/ # Business rules registry, models, builtin rules
│ ├── settings/ # Domain settings base
│ ├── constants/ # Field definitions, placeholders
│ ├── utils/ # time.py (utc_now), validation.py
│ ├── errors.py # Domain-specific exceptions
│ └── value_objects.py
├── application/ # Use-cases/services
│ ├── services/
│ │ ├── meeting/ # MeetingService (CRUD, segments, annotations, summaries, state)
│ │ ├── identity/ # IdentityService (context, workspace, defaults)
│ │ ├── calendar/ # CalendarService (connection, events, oauth, sync)
│ │ ├── summarization/ # SummarizationService, TemplateService, ConsentManager
│ │ ├── project_service/ # CRUD, members, roles, rules, active project
│ │ ├── recovery/ # RecoveryService (meeting, job, audio recovery)
│ │ ├── webhook_service.py
│ │ ├── ner_service.py
│ │ ├── export_service.py
│ │ ├── trigger_service.py
│ │ ├── retention_service.py
│ │ ├── auth_service.py
│ │ ├── auth_workflows.py
│ │ ├── auth_integration_manager.py
│ │ ├── auth_token_exchanger.py
│ │ ├── auth_types.py
│ │ ├── auth_constants.py
│ │ └── protocols.py
│ └── observability/ # Observability ports
├── infrastructure/ # Implementations
│ ├── audio/ # sounddevice capture, ring buffer, VU levels, playback, writer, reader
│ ├── asr/ # faster-whisper engine, VAD segmenter, streaming, DTOs
│ ├── auth/ # OIDC discovery, registry, presets
│ ├── diarization/ # Session, assigner, engine (streaming: diart, offline: pyannote)
│ ├── summarization/# CloudProvider, OllamaProvider, MockProvider, parsing, citation verifier, template renderer
│ ├── triggers/ # Calendar, audio_activity, foreground_app providers
│ ├── persistence/ # SQLAlchemy + asyncpg + pgvector
│ │ ├── database.py # create_async_engine, create_async_session_factory
│ │ ├── models/ # ORM models (core/, identity/, integrations/, entities/, observability/, organization/)
│ │ ├── repositories/ # Repository implementations
│ │ │ ├── meeting_repo.py
│ │ │ ├── segment_repo.py
│ │ │ ├── summary_repo.py
│ │ │ ├── annotation_repo.py
│ │ │ ├── entity_repo.py
│ │ │ ├── webhook_repo.py
│ │ │ ├── preferences_repo.py
│ │ │ ├── asset_repo.py
│ │ │ ├── summarization_template_repo.py
│ │ │ ├── diarization_job/
│ │ │ ├── integration/
│ │ │ ├── identity/
│ │ │ ├── usage_event/
│ │ │ └── _base/ # BaseRepository with _execute_scalar, _execute_scalars, _add_and_flush
│ │ ├── unit_of_work/
│ │ ├── memory/ # In-memory implementations
│ │ └── migrations/ # Alembic migrations
│ ├── security/ # Keystore (keyring + AES-GCM), protocols, crypto/
│ ├── crypto/ # Cryptographic utilities
│ ├── export/ # Markdown, HTML, PDF (WeasyPrint), formatting helpers
│ ├── webhooks/ # WebhookExecutor (delivery, signing, metrics)
│ ├── converters/ # ORM ↔ domain (orm, webhook, ner, calendar, integration, asr)
│ ├── calendar/ # Google/Outlook adapters, OAuth flow
│ ├── ner/ # spaCy engine
│ ├── observability/# OpenTelemetry tracing, usage tracking
│ ├── metrics/ # Metric collection
│ ├── logging/ # Log buffer utilities
│ └── platform/ # Platform-specific code
├── grpc/ # gRPC server and client
│ ├── server/ # Server entry point (__main__.py, __init__.py)
│ ├── service.py # NoteFlowServicer (composes mixins)
│ ├── client.py # Python gRPC client wrapper
│ ├── _mixins/ # Modular RPC implementations
│ │ ├── streaming/ # ASR streaming (package)
│ │ │ ├── _mixin.py # Main StreamingMixin class
│ │ │ ├── _session.py # Session management
│ │ │ ├── _asr.py # ASR processing
│ │ │ ├── _processing/ # Audio processing pipeline
│ │ │ │ ├── _audio_ops.py
│ │ │ │ ├── _chunk_tracking.py
│ │ │ │ ├── _congestion.py
│ │ │ │ ├── _constants.py
│ │ │ │ ├── _types.py
│ │ │ │ └── _vad_processing.py
│ │ │ ├── _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
│ │ ├── meeting/ # Meeting lifecycle (package)
│ │ │ ├── meeting_mixin.py
│ │ │ ├── _project_scope.py
│ │ │ └── _stop_ops.py
│ │ ├── summarization.py # Summary generation
│ │ ├── annotation.py # Segment annotations CRUD
│ │ ├── export.py # Document export
│ │ ├── entities.py # Named entity extraction
│ │ ├── calendar.py # Calendar sync
│ │ ├── webhooks.py # Webhook management
│ │ ├── preferences.py # User preferences
│ │ ├── observability.py # Usage tracking, metrics
│ │ ├── sync.py # State synchronization
│ │ ├── identity.py # Identity operations
│ │ ├── projects.py # Project operations
│ │ ├── oidc.py # OIDC operations
│ │ ├── converters.py # Protobuf ↔ domain converters
│ │ ├── errors.py # gRPC error helpers
│ │ ├── protocols.py # ServicerHost protocol
│ │ └── _audio_helpers.py # Audio utilities
│ ├── _client_mixins/ # Python client mixins
│ │ ├── streaming.py
│ │ ├── meeting.py
│ │ ├── diarization.py
│ │ ├── export.py
│ │ ├── annotation.py
│ │ ├── converters.py
│ │ └── protocols.py
│ ├── interceptors/ # gRPC server interceptors
│ │ └── identity.py # Identity context propagation
│ └── proto/ # Protobuf definitions and generated stubs
├── cli/ # CLI tools
│ ├── __main__.py # CLI entry point
│ ├── retention.py # Retention management
│ ├── constants.py # CLI constants
│ └── models/ # Model commands (package)
│ ├── _download.py
│ ├── _parser.py
│ ├── _registry.py
│ ├── _status.py
│ └── _types.py
└── config/ # Configuration
├── settings/ # Pydantic settings (_base, _features, _server, _security, etc.)
├── constants.py # Application constants
└── feature_flags.py
Client Architecture (client/src/)
client/src/
├── api/ # API layer with adapters
│ ├── 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
│ ├── core.ts
│ ├── meetings.ts
│ ├── segments.ts
│ ├── diarization.ts
│ ├── annotations.ts
│ ├── templates.ts
│ ├── webhooks.ts
│ ├── calendar.ts
│ ├── entities.ts
│ ├── preferences.ts
│ ├── observability.ts
│ ├── triggers.ts
│ ├── audio.ts
│ ├── playback.ts
│ ├── apps.ts
│ └── readonly.ts
├── hooks/ # Custom React hooks
│ ├── use-diarization.ts
│ ├── use-cloud-consent.ts
│ ├── use-webhooks.ts
│ ├── use-oauth-flow.ts
│ ├── use-calendar-sync.ts
│ ├── use-entity-extraction.ts
│ ├── use-audio-devices.ts
│ ├── use-project.ts
│ ├── use-project-members.ts
│ ├── use-oidc-providers.ts
│ ├── use-auth-flow.ts
│ ├── use-integration-sync.ts
│ ├── use-integration-validation.ts
│ ├── use-secure-integration-secrets.ts
│ ├── use-guarded-mutation.ts
│ ├── use-panel-preferences.ts
│ ├── use-preferences-sync.ts
│ ├── use-meeting-reminders.ts
│ ├── use-recording-app-policy.ts
│ ├── use-post-processing.ts
│ ├── use-toast.ts
│ ├── use-mobile.tsx
│ └── post-processing/
├── contexts/ # React contexts
│ ├── connection-context.tsx # gRPC connection context
│ ├── connection-state.ts
│ ├── workspace-context.tsx # Workspace context
│ ├── workspace-state.ts
│ ├── project-context.tsx # Project context
│ └── project-state.ts
├── components/ # React components
│ ├── ui/ # Reusable UI components (shadcn/ui)
│ ├── recording/ # Recording-specific components
│ ├── settings/ # Settings panel components
│ ├── analytics/ # Analytics visualizations
│ ├── projects/ # Project components
│ ├── icons/ # Icon components
│ └── ... # Top-level components
├── pages/ # Route pages
│ ├── Home.tsx
│ ├── Meetings.tsx
│ ├── MeetingDetail.tsx
│ ├── Recording.tsx
│ ├── Projects.tsx
│ ├── ProjectSettings.tsx
│ ├── Settings.tsx
│ ├── settings/ # Settings sub-pages
│ ├── People.tsx
│ ├── Tasks.tsx
│ ├── Analytics.tsx
│ ├── Index.tsx
│ └── NotFound.tsx
├── lib/ # Utilities
│ ├── config/ # Configuration (server, defaults, app-config, provider-endpoints)
│ ├── cache/ # Client-side caching (meeting-cache)
│ ├── format.ts
│ ├── utils.ts
│ ├── time.ts
│ ├── crypto.ts
│ ├── cva.ts
│ ├── styles.ts
│ ├── tauri-events.ts
│ ├── preferences.ts
│ ├── preferences-sync.ts
│ ├── entity-store.ts
│ ├── speaker-utils.ts
│ ├── ai-providers.ts
│ ├── ai-models.ts
│ ├── integration-utils.ts
│ ├── default-integrations.ts
│ ├── status-constants.ts
│ ├── timing-constants.ts
│ ├── object-utils.ts
│ ├── error-reporting.ts
│ ├── client-logs.ts
│ ├── client-log-events.ts
│ ├── log-groups.ts
│ ├── log-converters.ts
│ ├── log-messages.ts
│ ├── log-summarizer.ts
│ └── log-group-summarizer.ts
├── types/ # Shared TypeScript types
└── test/ # Test utilities
Rust/Tauri Backend (client/src-tauri/src/)
src-tauri/src/
├── commands/ # Tauri IPC command handlers
│ ├── recording/ # capture.rs, device.rs, audio.rs, app_policy.rs
│ ├── playback/ # audio.rs, events.rs, tick.rs
│ ├── triggers/ # audio.rs, polling.rs
│ ├── meeting.rs
│ ├── diarization.rs
│ ├── annotation.rs
│ ├── export.rs
│ ├── summary.rs
│ ├── entities.rs
│ ├── calendar.rs
│ ├── webhooks.rs
│ ├── preferences.rs
│ ├── observability.rs
│ ├── sync.rs
│ ├── projects.rs
│ ├── identity.rs
│ ├── oidc.rs
│ ├── connection.rs
│ ├── audio.rs
│ ├── audio_testing.rs
│ ├── apps.rs
│ ├── apps_platform.rs
│ ├── diagnostics.rs
│ ├── shell.rs
│ └── testing.rs
├── grpc/ # gRPC client
│ ├── client/ # Client implementations by domain
│ │ ├── core.rs
│ │ ├── meetings.rs
│ │ ├── annotations.rs
│ │ ├── diarization.rs
│ │ ├── identity.rs
│ │ ├── projects.rs
│ │ ├── preferences.rs
│ │ ├── calendar.rs
│ │ ├── webhooks.rs
│ │ ├── observability.rs
│ │ ├── oidc.rs
│ │ ├── sync.rs
│ │ └── converters.rs
│ ├── types/ # Rust type definitions
│ │ ├── core.rs
│ │ ├── enums.rs
│ │ ├── identity.rs
│ │ ├── projects.rs
│ │ ├── preferences.rs
│ │ ├── calendar.rs
│ │ ├── webhooks.rs
│ │ ├── observability.rs
│ │ ├── oidc.rs
│ │ ├── sync.rs
│ │ └── results.rs
│ ├── streaming/ # Streaming converters
│ └── noteflow.rs # Generated protobuf types
├── state/ # Runtime state management
│ ├── app_state.rs
│ ├── preferences.rs
│ ├── playback.rs
│ └── types.rs
├── audio/ # Audio capture and playback
├── cache/ # Memory caching
├── crypto/ # Cryptographic operations
├── events/ # Tauri event emission
├── triggers/ # Trigger detection
├── error/ # Error types
├── identity/ # Identity management
├── config.rs # Configuration
├── constants.rs # Constants
├── helpers.rs # Helper functions
├── oauth_loopback.rs # OAuth callback server
├── main.rs # Application entry point
└── lib.rs # Library exports
Database
PostgreSQL with pgvector extension. Async SQLAlchemy with asyncpg driver.
# Alembic migrations
alembic upgrade head
alembic revision --autogenerate -m "description"
Connection via NOTEFLOW_DATABASE_URL env var or settings.
ORM Models (persistence/models/)
| Directory | Models |
|---|---|
core/ |
MeetingModel, SegmentModel, SummaryModel, AnnotationModel, DiarizationJobModel |
identity/ |
UserModel, WorkspaceModel, WorkspaceMembershipModel, ProjectModel, ProjectMembershipModel, SettingsModel |
integrations/ |
IntegrationModel, IntegrationSecretModel, CalendarEventModel, MeetingCalendarLinkModel, WebhookConfigModel, WebhookDeliveryModel |
entities/ |
NamedEntityModel, SpeakerModel |
observability/ |
UsageEventModel |
organization/ |
SummarizationTemplateModel, TaskModel, TagModel |
Testing Conventions
- Test files:
test_*.py, functions:test_* - Markers:
@pytest.mark.slow(model loading),@pytest.mark.integration(external services) - Integration tests use testcontainers for PostgreSQL
- Asyncio auto-mode enabled
- React unit tests use Vitest; e2e tests use Playwright in
client/e2e/
Test Quality Gates (tests/quality/)
After any non-trivial changes, run:
pytest tests/quality/
This suite enforces:
| Check | Description |
|---|---|
test_test_smells.py |
No assertion roulette, no conditional test logic, no loops in tests |
test_magic_values.py |
No magic numbers in assignments |
test_code_smells.py |
Code quality checks |
test_duplicate_code.py |
No duplicate code patterns |
test_stale_code.py |
No stale/dead code |
test_decentralized_helpers.py |
Helpers consolidated properly |
test_unnecessary_wrappers.py |
No unnecessary wrapper functions |
test_baseline_self.py |
Baseline validation self-checks |
Global Fixtures (tests/conftest.py)
Do not redefine these fixtures:
| Fixture | Description |
|---|---|
reset_context_vars |
Reset logging context variables |
mock_uow |
Mock Unit of Work |
crypto |
Crypto utilities |
meetings_dir |
Temporary meetings directory |
webhook_config |
Single-event webhook config |
webhook_config_all_events |
All-events webhook config |
sample_datetime |
Sample datetime |
calendar_settings |
Calendar settings |
meeting_id |
Sample meeting ID |
sample_meeting |
Sample Meeting entity |
recording_meeting |
Recording-state Meeting |
sample_rate |
Audio sample rate |
mock_grpc_context |
Mock gRPC context |
mockasr_engine |
Mock ASR engine |
mock_optional_extras |
Mock optional extras |
mock_oauth_manager |
Mock OAuth manager |
memory_servicer |
In-memory servicer |
approx_float |
Approximate float comparison |
approx_sequence |
Approximate sequence comparison |
Code Style
Python
- Python 3.12+, 100-char line length
- 4-space indentation
- Naming:
snake_casemodules/functions,PascalCaseclasses,UPPER_SNAKE_CASEconstants - Strict basedpyright (0 errors, 0 warnings, 0 notes required)
- Ruff for linting (E, W, F, I, B, C4, UP, SIM, RUF)
- Module soft limit 500 LoC, hard limit 750 LoC
- Generated
*_pb2.py,*_pb2_grpc.pyexcluded from lint
TypeScript
- Biome for linting and formatting
- Single quotes, 100 char width
- Strict TypeScript (noEmit checks)
Rust
rustfmtfor formattingclippyfor linting (warnings treated as errors)
Type Safety (Zero Tolerance)
Forbidden Patterns (Python)
| Pattern | Why Blocked | Alternative |
|---|---|---|
# type: ignore |
Bypasses type safety | Fix the actual type error |
# pyright: ignore |
Bypasses type safety | Fix the actual type error |
Any type annotations |
Creates type safety holes | Use Protocol, TypeVar, TypedDict, or specific types |
| Magic numbers | Hidden intent | Define typing.Final constants |
| Loops in tests | Non-deterministic | Use @pytest.mark.parametrize |
| Conditionals in tests | Non-deterministic | Use @pytest.mark.parametrize |
| Multiple assertions without messages | Hard to debug | Add assertion messages |
Type Resolution Hierarchy
When facing dynamic types:
Protocol— For duck typing (structural subtyping)TypeVar— For genericsTypedDict— For structured dictionariescast()— Last resort (with comment explaining why)
Validation Requirements
After any code changes:
source .venv/bin/activate && basedpyright src/noteflow/
Expected output: 0 errors, 0 warnings, 0 notes
Protected Files (Require Explicit Permission)
| File/Directory | What's Blocked |
|---|---|
Makefile |
All modifications |
tests/quality/ (except baselines.json) |
All modifications |
pyproject.toml, ruff.toml, pyrightconfig.json |
All edits |
biome.json, tsconfig.json, .eslintrc* |
All edits |
.rustfmt.toml, .clippy.toml |
All edits |
Quality Gate Requirement
Before completing any code changes:
make quality
All quality checks must pass.
Policy: No Ignoring Pre-existing Issues
If you encounter lint errors, type errors, or test failures—even if they existed before your changes—you must either:
- Fix immediately (for simple issues)
- Add to todo list (for complex issues)
- Launch a subagent to fix (for parallelizable work)
Proto/gRPC
Proto definitions: src/noteflow/grpc/proto/noteflow.proto
Regenerate after proto changes:
python -m grpc_tools.protoc -I src/noteflow/grpc/proto \
--python_out=src/noteflow/grpc/proto \
--grpc_python_out=src/noteflow/grpc/proto \
src/noteflow/grpc/proto/noteflow.proto
Then run stub patching:
python scripts/patch_grpc_stubs.py
Sync Points (High Risk of Breakage)
When changing proto:
- Python stubs — Regenerate
*_pb2.py,*_pb2_grpc.py - Server mixins — Update
src/noteflow/grpc/_mixins/ - Python client — Update
src/noteflow/grpc/client.py - Rust types — Generated by
client/src-tauri/build.rs - Rust commands — Update
client/src-tauri/src/commands/ - TypeScript types — Update
client/src/api/types/ - TypeScript adapter — Update
client/src/api/tauri-adapter.ts
Key Subsystems
Speaker Diarization
- Streaming: diart for real-time speaker detection
- Offline: pyannote.audio for post-meeting refinement
- gRPC:
RefineSpeakerDiarization,GetDiarizationJobStatus,RenameSpeaker
Summarization
- Providers: CloudProvider (Anthropic/OpenAI), OllamaProvider (local), MockProvider (testing)
- Templates: Configurable tone, format, verbosity
- Citation verification: Links summary claims to transcript evidence
- Consent: Cloud providers require explicit user consent
Export
- Formats: Markdown, HTML, PDF (via WeasyPrint)
- Content: Transcript with timestamps, speaker labels, summary
Named Entity Recognition (NER)
- Engine: spaCy with transformer models
- Categories: person, company, product, technical, acronym, location, date, other
- Segment tracking: Entities link to source
segment_ids
Trigger Detection
- Signals: Calendar proximity, audio activity, foreground app
- Actions: IGNORE, NOTIFY, AUTO_START
Webhooks
- Events:
meeting.completed,summary.generated,recording.started,recording.stopped - Delivery: Exponential backoff retries
- Security: HMAC-SHA256 signing
Authentication
- OIDC: OpenID Connect with discovery
- Providers: Configurable via OIDC registry
Feature Flags
| Flag | Default | Controls |
|---|---|---|
NOTEFLOW_FEATURE_TEMPLATES_ENABLED |
true |
AI summarization templates |
NOTEFLOW_FEATURE_PDF_EXPORT_ENABLED |
true |
PDF export format |
NOTEFLOW_FEATURE_NER_ENABLED |
false |
Named entity extraction |
NOTEFLOW_FEATURE_CALENDAR_ENABLED |
false |
Calendar sync |
NOTEFLOW_FEATURE_WEBHOOKS_ENABLED |
true |
Webhook notifications |
Access via get_feature_flags().<flag_name> or get_settings().feature_flags.<flag_name>.
Common Pitfalls Checklist
When Adding New Features
- Update proto schema first (if gRPC involved)
- Regenerate Python stubs
- Run
scripts/patch_grpc_stubs.py - Implement server mixin
- Update Python client wrapper
- Update Rust commands
- Update TypeScript adapter
- Update TypeScript types
- Add tests (both backend and client)
- Run
make quality
When Changing Database Schema
- Update ORM models in
persistence/models/ - Create Alembic migration
- Update repository implementation
- Update UnitOfWork if needed
- Update converters in
infrastructure/converters/
When Modifying Existing Code
- Search for all usages first
- Update all call sites
- Run
make quality - Run relevant tests
Known Issues & Technical Debt
See docs/triage.md for tracked technical debt.
See docs/sprints/ for feature implementation plans.
Configuration & Security
- Runtime settings from
.envorNOTEFLOW_environment variables - Settings module:
src/noteflow/config/settings/ - Keep secrets and credentials out of the repo
- Use
.envfor local development configuration
Commit & Pull Request Guidelines
- Use Conventional Commits:
feat:,fix:,chore:,docs:,refactor:,test: - Include concise scope when helpful:
feat(grpc): add streaming backpressure - PRs should:
- Describe the change clearly
- Link related issues/specs
- Note any DB or proto changes
- Include UI screenshots for client changes
- Pass all quality checks (
make quality)