Conclave Docs

Data model

Schema highlights and the load-bearing migrations.

Conclave persists everything in one SQLite file inside the TEE (relational + FTS5 + sqlite-vec vectors), managed by SQLAlchemy 2 + Alembic. Alembic auto-applies on boot. VFTEE keeps its own sealed SQLite voiceprint store.

Key tables (conceptual)

  • transcript_sessions — the meeting: owner_user_id, recorder_user_id, owner_only, created_at, metadata (source/platform/origin), enrichment_state.
  • raw_diarization — write-once span-level truth {start, end, local_speaker}. Never mutated; edits and identity live in overlays.
  • transcript_v2 + vocab — the editable, span-annotated doc (draft → approved) + personal vocabulary.
  • live_segments — append-only live stream for the SSE view.
  • resolved_speakers — the identity overlay {label: {voiceprint_id, name, confidence}}.
  • chunks + FTS5 + embeddings; entities / facts / obligations — bi-temporal (valid_to / superseded_by).
  • workspaces / workspace_members / workspace_invites / meeting_workspace_shares — the membership + sharing graph.
  • transcript_versions + version_events — the immutable version chain (#3): each approved edit appends a sealed version (via the #21 seal signer); version_events records who/what/when.
  • personal_access_tokens (hashed conclave_pat_…) + oauth_clients — the external agent surface (workspace PATs + OAuth "Connect with Conclave").
  • magic_links, audio-store metadata, feedback, T&C acceptance.

Load-bearing migrations

MigrationWhat it introduced
0002workspaces / members / shares / magic_links
0007entities / facts / obligations
0012 → 0024share scope enum → per-artifact {transcript, insights, audio} flags
0013retention
0016live_segments
0018transcript_v2 + vocab
0022audio-store
0023in-person agenda
0025user T&C
0027workspace_invites + meeting_workspace_shares + inperson_recorder + recorder_user_id / owner_only (#32)
0028workspaces.type column — personal vs team split
0029data backfill: re-point in-person session ownership from workspace-creator → actual recorder
0032workspace PATs (hashed conclave_pat_…) — external read API
0034OAuth 2.1 client registry ("Connect with Conclave")
0035re-key speaker_tags onto the roster slot (slot_ref, #23/#124) — not additive: snapshot before deploying
0036transcript_versions + version_events (#3)
0037one-time backfill: an imported v1 for every already-published session (INSERT-only, #3)

The raw / derived split is load-bearing: raw_diarization is immutable and never serialized unless authorized; everything else (overlays, v2, insights, KB) is derived and re-derivable.

Worked example: the sharing scopes (how to add one)

Sharing is per-artifact booleans, not an enum (that was the 0012 → 0024 change). Concretely:

  • Columns: share_transcript, share_insights, share_audio on the share record.
  • Model: ShareConfig in infra/workspaces.py is the single place a share's booleans are built.
  • Enforcement gates: can_see_transcript / can_see_insights / can_see_audio in api/transcripts_routes.py decide what a viewer's response includes (insights are independently withholdable).

To add a new scope (e.g. "share attachments"): add the boolean column via a new Alembic migration (mirror 0024), extend ShareConfig, add a can_see_attachments gate alongside the others, and surface it in the share UI. This is the #31 pattern end to end.

On this page