Menu

Session Management

Relevant source files

Purpose and Scope

This document describes the session management system in Hyprnote, which handles the creation, storage, retrieval, and lifecycle management of note-taking sessions. A session represents a single note-taking event, potentially linked to a calendar event, and contains transcription data, notes, participants, and metadata.

For information about real-time transcription during an active session, see Real-time Transcription. For calendar event synchronization with sessions, see Calendar Integration. For the database system that persists sessions, see Database System.

Overview

A session is the core data entity in Hyprnote. Each session captures:

  • Timestamped transcription words with optional speaker identification
  • User-authored notes in both raw and AI-enhanced HTML formats
  • Association with calendar events and participants
  • Recording timestamps if audio was captured
  • Pre-meeting context and metadata

Sessions are persisted in a local SQLite database (libsql) with optional cloud synchronization via Turso. The system uses a Tauri plugin architecture where Rust backend operations are exposed to the React frontend through type-safe TypeScript bindings.

Sources: crates/db-user/src/sessions_types.rs1-114 crates/db-user/src/sessions_ops.rs1-506

Session Data Model

The Session struct is defined in crates/db-user/src/sessions_types.rs5-23 with the following key fields:

FieldTypePurpose
idString (UUID)Unique session identifier
created_atDateTimeSession creation timestamp
visited_atDateTimeLast access timestamp for sorting
user_idStringOwner of the session
calendar_event_idOptionOptional link to calendar event
titleStringSession title (user-editable)
raw_memo_htmlStringUser-authored note content
enhanced_memo_htmlOptionAI-enhanced version of notes
wordsVecTranscribed words with timing
record_start / record_endOption<DateTime>Recording time bounds
pre_meeting_memo_htmlOptionContext prepared before meeting

Sources: crates/db-user/src/sessions_types.rs5-72 plugins/db/js/bindings.gen.ts459

Session Lifecycle

Session Creation

Sessions are created via upsert_session() which performs an INSERT or UPDATE operation. The implementation at crates/db-user/src/sessions_ops.rs266-335 uses an ON CONFLICT(id) DO UPDATE SQL pattern to enable both creation and updates with a single operation.

New sessions are typically created:

  1. When user starts a new note manually
  2. Automatically when a calendar event starts and notification is triggered
  3. During initial onboarding with pre-populated sample data

Session Access Tracking

The visit_session() function at crates/db-user/src/sessions_ops.rs98-107 updates the visited_at timestamp whenever a user accesses a session. This enables the "Recently Visited" filter to show sessions in chronological access order.

Session Cleanup

The cleanup_sessions() method at crates/db-user/src/sessions_ops.rs16-31 removes empty sessions where:

  • title is empty
  • raw_memo_html is empty
  • enhanced_memo_html is NULL or empty
  • pre_meeting_memo_html is NULL or empty
  • conversations is empty array

Sources: crates/db-user/src/sessions_ops.rs16-335 plugins/db/src/commands/sessions.rs77-90

Session Operations Architecture

Command Handler Pattern

All session commands follow a consistent pattern, as seen in plugins/db/src/commands/sessions.rs77-90:

The pattern involves:

  1. State acquisition: Lock the ManagedState mutex to access database
  2. Database validation: Ensure database is initialized with ok_or(Error::NoneDatabase)
  3. Operation execution: Call the corresponding UserDatabase method
  4. Error mapping: Convert Result<T, crate::Error> to Result<T, String> for Tauri

Type-Safe Bindings

The tauri-specta library generates TypeScript bindings at plugins/db/js/bindings.gen.ts58-265 These provide:

  • Full type safety between Rust and TypeScript
  • Automatic serialization/deserialization
  • Result types with status discrimination

Sources: plugins/db/src/commands/sessions.rs1-266 plugins/db/js/bindings.gen.ts58-265 plugins/db/src/lib.rs22-80

Session Filtering and Querying

The ListSessionFilter type at crates/db-user/src/sessions_types.rs85-113 provides flexible session querying:

Filter Types

Filter TypeImplementationUse Case
SearchFull-text search across title, memos, and participant dataUser search box
Recently VisitedORDER BY visited_at DESCDefault view showing recent sessions
Date RangeFilter by created_at or event start_dateCalendar view, date pickers
Tag FilterJOIN with tags_sessions tableFiltered views by topic/category

Search Implementation

The search filter at crates/db-user/src/sessions_ops.rs129-157 searches multiple fields:

  • Session title (prioritized in ORDER BY)
  • Enhanced memo HTML (with tags stripped via REPLACE)
  • Raw memo HTML (with tags stripped)
  • Participant full names
  • Participant email addresses

The query uses LIKE '%query%' pattern matching and returns DISTINCT results since participants are joined.

Date Range Behavior

The date range filter at crates/db-user/src/sessions_ops.rs172-196 has special logic:

  • If calendar_event_id IS NULL, filter by session's created_at
  • If calendar_event_id IS NOT NULL, filter by joined event's start_date
  • This ensures sessions appear at the correct time in calendar views

Sources: crates/db-user/src/sessions_types.rs85-113 crates/db-user/src/sessions_ops.rs119-243

Session Participants

Sessions maintain a many-to-many relationship with Human entities through the session_participants join table. Participants can be added, removed (soft-deleted), and listed.

Participant Operations

Implementation Details

Adding Participants crates/db-user/src/sessions_ops.rs357-370:

  • Uses INSERT OR REPLACE to handle duplicate adds
  • Sets deleted = FALSE to restore previously removed participants
  • Idempotent operation - safe to call multiple times

Removing Participants crates/db-user/src/sessions_ops.rs372-385:

  • Soft delete via UPDATE deleted = TRUE
  • Preserves history of participant associations
  • Allows UI to show "removed" state if needed

Listing Participants crates/db-user/src/sessions_ops.rs387-408:

  • JOINs with humans table to get full participant details
  • Filters by deleted = FALSE OR deleted IS NULL
  • Returns full Human objects with name, email, job title, etc.

Sources: crates/db-user/src/sessions_ops.rs357-408 plugins/db/src/commands/sessions.rs185-245

Session-Calendar Event Association

Sessions can be linked to calendar events, creating a bidirectional relationship that enables automatic session creation from calendar notifications and context enrichment from meeting details.

Association Operations

Setting Association crates/db-user/src/sessions_ops.rs337-355:

  • Updates calendar_event_id column
  • Accepts None to unlink an event
  • Used when user manually links/unlinks calendar events

Retrieving Linked Event crates/db-user/src/sessions_ops.rs410-432:

  • JOINs events and sessions tables
  • Returns full Event object with calendar details
  • Returns None if no event is linked

Use Cases

  1. Automatic Session Creation: When calendar notification fires, create session with calendar_event_id pre-populated
  2. Context Enrichment: Populate session title from event name, participants from event attendees
  3. Calendar View: Show sessions on calendar at correct date/time using event's start_date
  4. Recurrence Handling: Events table tracks is_recurring flag for repeated meetings

Sources: crates/db-user/src/sessions_ops.rs337-432 plugins/db/src/commands/sessions.rs164-183

Special Sessions

The system maintains two hardcoded special session IDs for onboarding and post-signup flows.

Onboarding Session

ID: df1d8c52-6d9d-4471-aff1-5dbd35899cbe

Defined at crates/db-user/src/sessions_ops.rs8-10:

The onboarding session is created during user initialization via init::onboarding() at crates/db-user/src/init.rs9-24:

  • Loads seed data from plugins/db/seed/onboarding.json
  • Injects pre-authored HTML content from crates/db-user/assets/onboarding-raw.html
  • Provides sample transcription words to demonstrate the editor interface
  • Substitutes {{ CURRENT_USER_ID }} with actual user ID

Thank You Session

ID: 872cf207-6a28-4229-bd66-492d0dce43c0

Defined at crates/db-user/src/sessions_ops.rs12-14:

The thank you session:

Both special sessions are:

  • Excluded from regular session cleanup
  • Pre-populated with formatted content
  • Used to guide new users through the interface

Sources: crates/db-user/src/sessions_ops.rs8-14 crates/db-user/src/init.rs9-24 crates/db-user/src/seed.rs55-65

Transcription Data Management

Sessions store transcription data as a JSON-serialized array of Word2 objects in the database.

Word2 Structure

From plugins/db/js/bindings.gen.ts464:

Storage and Retrieval

Storage at crates/db-user/src/sessions_ops.rs324:

  • Serializes Vec<Word2> to JSON string via serde_json::to_string()
  • Stored in words TEXT column
  • Updated on every upsert_session() call

Retrieval via get_words() at crates/db-user/src/sessions_ops.rs41-60:

  • Queries single session by ID
  • Deserializes JSON with fallback to empty array
  • Returns full word array for playback and editing

Onboarding Words

The get_words_onboarding() function at crates/db-user/src/sessions_ops.rs33-39 returns hardcoded sample transcription:

  • Loaded from hypr_data::english_7::WORDS_JSON
  • Used to populate the special onboarding session
  • Provides realistic demo without actual transcription

Speaker Identification

Word2.speaker can be:

  • Unassigned: { type: "unassigned", value: { index: 0 } } - Detected speaker but not identified
  • Assigned: { type: "assigned", value: { id: "human-uuid", label: "John Doe" } } - Linked to Human entity
  • Null: No speaker detection (e.g., single-speaker recordings)

Sources: crates/db-user/src/sessions_ops.rs33-60 plugins/db/js/bindings.gen.ts460-464 plugins/db/src/commands/sessions.rs20-72

Frontend-Backend Integration

The session management system exposes 17 commands to the frontend through the DB plugin.

Available Commands

From plugins/db/build.rs7-22:

CommandPurposeParametersReturn Type
onboarding_session_idGet special session IDNoneString
thank_you_session_idGet special session IDNoneString
upsert_sessionCreate/update sessionSession objectSession
list_sessionsQuery sessionsOptional filterSession[]
get_sessionRetrieve by filterGetSessionFilterSession | null
visit_sessionUpdate visited_atsession_idvoid
delete_sessionRemove sessionsession_idvoid
set_session_eventLink calendar eventsession_id, event_idvoid
session_add_participantAdd participantsession_id, human_idvoid
session_remove_participantRemove participantsession_id, human_idvoid
session_list_participantsGet participantssession_idHuman[]
session_list_deleted_participant_idsGet removed IDssession_idString[]
session_get_eventGet linked eventsession_idEvent | null
get_wordsGet transcriptionsession_idWord2[]
get_words_onboardingGet demo wordsNoneWord2[]

Extension Trait Methods

The DatabasePluginExt trait at plugins/db/src/ext.rs19-27 provides higher-level session operations:

These methods are used internally by other Tauri commands and plugins to interact with sessions without directly invoking frontend-facing commands.

Permission Model

All session commands require explicit permission grants defined in plugins/db/permissions/default.toml4-18 The default permission set includes all session operations, but applications can restrict individual commands through Tauri's capability system.

Sources: plugins/db/build.rs7-22 plugins/db/permissions/default.toml4-18 plugins/db/src/ext.rs19-27

Database Migrations

Session schema is managed through versioned migrations in crates/db-user/src/lib.rs145-173 Relevant migrations:

MigrationFileChanges
5sessions_migration.sqlInitial sessions table
6session_participants_migration.sqlJoin table for participants
14sessions_migration_1.sqlSchema update
15sessions_migration_2.sqlSchema update
16sessions_migration_3.sqlSchema update
17sessions_migration_4.sqlSchema update
20session_participants_migration_1.sqlParticipant schema update

The migration system at crates/db-user/src/lib.rs175-180:

  • Applies migrations sequentially in append-only order
  • Cannot reorder or modify existing migrations
  • Ensures consistent schema across all installations

Sources: crates/db-user/src/lib.rs145-180