v0.5.0
Deployment and release hardeningReady to shipRelease tooling, deployment shapes, and the security and correctness work that came out of a full rehearsal.
220 issues
- #455 fix(transcription): storage.py overwrites MediaFile.duration with 0.0, and speaker sets are non-deterministic
- #456 fix(transcription): garbage-word cleanup edits text but not words, and rewrites whitespace on every segment
- #470 ASR providers: real defects found writing #445 test coverage (punctuation loss, retry never fires, timeout bool discarded, wrong response_format)
- #584 Lite mode: cloud-ASR speaker embeddings silently never complete (GPU-only queue, no lite worker)
- #362 feat: Document ingestion & knowledge base — parse, index, and chat over documents alongside transcripts
- #174 Refactor: Split oversized frontend components (FileDetail, SettingsModal, TranscriptDisplay, Speakers)
- #298 bug(upload): single-file limit is 15 GB but multi-file drop rejects at 2 GB
- #301 bug(frontend): MediaFile status union is missing queued, downloading, and quarantined
- #302 bug(frontend): audioExtractionService hashes on the main thread — tab freeze / OOM on large video
- #326 i18n: ~65 remaining bypasses in the service/store layer + tag-shape contract disagreement
- #327 upload: no browser-side presigned multipart or resume for multi-GB files (A2.9 remainder)
- #335 bug(file-detail): tag changes never propagate — TagsSection says "re-emit to parent" but never dispatches
- #338 cleanup: `reactiveFile` is a write-only store — 13 writes, zero readers
- #342 bug(upload): client-side SHA-256 silently skips duplicate detection above ~4 GB
- #352 bug(file-detail): renaming a speaker does not update the transcript until a full page reload
- #376 Frontend dead-code cleanup: knip audit findings
- #452 Responsive: nav overflows at 1280px and clips the user menu; 1280 is an untested breakpoint
- #475 Test suite: frontend statement coverage is 14.27%; core service/store/api logic largely untested
- #489 Watch sources: per-file management UI is entirely unbuilt despite full backend/API support
- #490 Watch sources: per-source email-notification linking UI is entirely unbuilt despite full backend/API support
- #527 Gallery: virtualized rendering and real thumbnails
- #578 task(backend): confirm whether speaker rename/verify still live-updates other connected clients via WebSocket
- #583 ShareCollectionModal hardcodes canManage=true regardless of collection ownership
- #585 fix(frontend): file detail page canEdit fails open on missing/null my_permission
- #645 Waveform seek can stall ~10-30s on a fresh page load before media metadata is ready
- #596 fix(llm-provider): Bedrock LLM provider is implemented but unreachable — no schema/UI wiring
- #193 [FEATURE] Improve diarization at boundaries
- #299 bug(diarization): _normalize_speaker_label raises TypeError on every call (object.__new__ on an abstract class)
- #482 speaker_processor.mark_overlapping_segments loses overlap data when a segment spans two overlap regions
- #483 Duplicate normalize_speaker_label implementation in speaker_processor.py diverges from the canonical version
- #520 diarization follow-ups that need a GPU window: speakrs boundary fixture twin + sidecar EP smoke test
- #571 task(asr): migrate CPU-lite + speaker-embedding path off PyTorch/PyAnnote onto native diar-native
- #579 diar-native: WAV write failure hard-fails the pipeline instead of degrading to PyAnnote fallback
- #621 fix(frontend): local diarization settings/About/reprocess text still credit PyAnnote as primary, not diar-native
- #21 [ENHANCEMENT] Implement Comprehensive Testing and Enable CI/CD Pipeline
- #26 [FEATURE] Automatic Bucket Processing with User Access Controls
- #123 E2E Test Expansion: Gallery, Upload, Settings, Transcription, Search & CI/CD
- #189 [BUG] Quick Installation documenation incorrect
- #190 [FEATURE] auto-ingest a file share or support api uploads
- #234 Testing follow-ups: coverage ratchet, responsive E2E, deferred dep majors
- #241 Modernize UUID columns: native pg uuid type + generation strategy review
- #242 Backup extension: MinIO media mirror (OpenSearch snapshots DONE in #239)
- #243 Back up encryption keys / .env alongside the database (or backups are unrecoverable)
- #244 Surface scheduled-backup failures (Prometheus metric + notification)
- #245 Operational: re-ingest the media corpus in place after #239 merges (GPU 1)
- #272 Latent always-False FileStatus string comparisons (found by the py312 codemod audit)
- #293 bug(watch-sources): SMB download size-mismatch check is unreachable — truncated downloads import silently
- #294 bug(watch-sources): watch.fs_events_enabled is a no-op — no watchdog Observer exists
- #295 bug(watch-sources): watch.max_concurrent_imports is a per-scan slice cap, not concurrency
- #297 bug(tests): pytest.mark.gpu is unregistered and silently ungated — GPU tests run in fast CI, integration gate under-covers
- #303 docs(release-tests): README claims hard isolation, but the scripts use live ports and stock container names
- #320 perf/correctness: `async def` functions that never await block the event loop (OpenSearchSummaryService + 78 endpoint handlers)
- #325 test: `@pytest.mark.unit` test downloads a HuggingFace model and randomly reddens CI
- #334 bug(sse): bulk-export stream can hang forever — check-then-subscribe lost-wakeup race
- #343 bug(opentr.sh): --port-offset does not offset — Compose appends port lists
- #347 bug(opentr.sh): --fresh cannot isolate the ldap/smb/monitoring test overlays
- #355 [BUG] Flower container always reports as unhealthy
- #389 Flaky tests: cross-worker Postgres deadlocks + order-dependent failure in migration/settings tests
- #397 test(routes): /api/auth/me/certificate has no frontend caller and no allow-list entry
- #398 Pre-existing defects surfaced by the release-engineering gates (2 failing tests + 4 schema findings)
- #399 fix(bench): engine/status gate on the dev stack's container names — the bench overlay renames everything to otbench-*
- #407 Unattended install aborts at the final step: set -e + pipefail on an absent optional .env key
- #408 Fresh-install release scenario is not repeatable: it reuses the previous run's database
- #409 Unattended install never persists HUGGINGFACE_TOKEN: every transcription fails
- #410 v0.5.0 BREAKING: existing v0.4.x deployments without REDIS_PASSWORD will fail to start after upgrade
- #411 Every production container reports its version as "unknown": compose blanks the baked APP_VERSION
- #412 rehearse stage can never reach Scenario B: Scenario A leaves its stack running
- #413 SECURITY: the release scan gate is fail-open — finding CRITICAL CVEs makes it PASS
- #414 SECURITY: the release scan gate scans the PREVIOUS release, not the release candidate
- #423 Upgrade Docusaurus 3.9.2 → 3.10.2 (MDX v3 content migration required)
- #431 Test suite: 81% of wall clock is one serialized worker + 8 lock barriers; 232 security tests never run; 113 modules untested
- #434 pre-commit stashes the WHOLE tree on every run — it has destroyed in-flight work twice
- #440 DB sessions held across slow work hang Alembic and wedge the database
- #445 Test suite: 41% of backend modules have no test reference; four authz decorators untested
- #446 Mutation testing: ~275 of 636 survivors are real gaps, not log noise — triage the top findings
- #447 Visual regression: all 8 baselines failing
- #450 auth_decorators.py + transcription_service.py are dead code (~650 LOC); require_verified_user doesn't verify
- #451 Visual regression: all 8 baselines depend on live mutable dev data and cannot be honestly refreshed
- #454 Test isolation: tests/unit fixtures vanish when a tests/*.py file is collected in the same run
- #457 fix(recovery): the request cap stops bounding requests exactly when fetches are failing
- #458 fix(gpu): a healthy GPU reports 'No GPU Available', and GPU_SCALE_DEFAULT_WORKER=true is silently False
- #459 mutation --verify: class-method mutants always UNVERIFIABLE (dedented diff matched against un-dedented source)
- #474 Test suite: 57 backend modules have zero test reference after #445/#470
- #485 Celery apply_async() intermittently dispatches to the default AMQP broker instead of the configured Redis one — every admin "Run now" action 500s
- #486 test_speaker_metadata.py fails intermittently under xdist parallelism (passes clean standalone)
- #487 Golden-fixture drift: test_boundary_regression word-count mismatch (2282 ref vs 2251 hyp) — real accuracy drift or stale fixture?
- #491 NLTK/offline: corpora fetched at runtime, airgap coverage incomplete
- #492 requirements.txt pins almost nothing: venv and container diverged by 120 packages (18 major)
- #493 Integration phase: 95 tests take >30 min, cannot pass on 12GB GPU, and has no per-test timeout
- #500 Dockerfile.blackwell: huggingface_hub==0.23.5 downgrade makes `import transformers` fail outright
- #522 Ingest real media into dev by pulling from the NAS store (first true ASR + diarization run)
- #528 BUG: --no-bindmount can serve a stale image, silently invalidating measurements
- #529 Final merge gate for feat/rag-transcript-intelligence: full suite, benchmarks, E2E
- #538 opentr.sh: load the diar-native overlay so dev runs the primary diarization engine, not its fallback
- #539 Audit every .env / .env.example variable: read-by-what, accurate, useful — and keep the template in sync
- #541 E2E: a speaker test persists prediction state onto a real profile (data-hygiene violation)
- #545 refactor(backend): audit duplicate public function names — two normalize_language implementations disagree
- #553 bug(opentr.sh): a plain 'start dev' has no port pre-flight, so a collision half-starts the stack
- #567 bug(config): five defects found by the .env audit — non-functional GPU clustering device, 3 phantom ASR aliases, unimplemented FedRAMP AC-2
- #568 bug(testing): DIARIZATION_VRAM_BUDGET_MB perf-gate test asserts a propagation mechanism that doesn't exist
- #577 task(testing): diarization GPU integration tests unrunnable via either documented path (venv torchaudio drift + benchmark container missing test deps)
- #580 fix-shared-volume-perms.sh: default chown GID (1000) doesn't match the image's appuser GID (999)
- #586 test(diarization): pyannote.ai cloud diarization provider has no direct test coverage
- #590 refactor(scripts): replace hand-rolled bash .env parsing + ad-hoc smoke scripts with python-dotenv + pytest
- #591 chore(docker): promote compose-only env vars to .env.example, fix TEMP_DIR name collision
- #592 Upgrade rehearsal proves the happy path; there's no failure-recovery doc or in-script guidance for a failed ./opentranscribe.sh update
- #597 CI: Release Validation dry-run fails on missing NAS mount, not a real deployment defect
- #598 Release rehearsal matrix has no coverage for opentr.sh backup/restore or opentranscribe.sh update --rollback
- #599 P0: opentr.sh restore silently fails to restore data — exits 0, reports success, changes nothing
- #600 P0: scheduled backup_service.py produces -Fc custom-format dumps with NO restore path anywhere in the repo
- #601 cleanup-test-users.py --execute (real DELETE FROM "user") has zero test coverage
- #602 fix-model-permissions.sh / fix-shared-volume-perms.sh have zero test coverage (chown on real data volumes)
- #604 backup.encrypt (scheduled/S3 backup gpg encryption) fails in production — gnupg not installed in backend image
- #607 UserLLMSettings.is_active is vestigial (always defaults True, never reflects the real active config) — silently defeats the e2e ensure_llm_provider fixture
- #608 docker-compose.llm-test.yml's default Gemma-4-E4B-AWQ config does not fit a 12GB GPU even with the entire card free — full-test-matrix.md's <=0.45 guidance is insufficient
- #609 Flower /api/workers never shows threads-pool Celery workers (gpu-scaled@*, gpu-transcription@*) — gpu-scale-smoke.sh cannot pass
- #610 opentr.sh restore silently lets the running (newer) app auto-migrate a just-restored older backup forward — blocks the rollback rehearsal's phase 15-17 chain
- #612 fix(testing): search-quality suite fails 2 unrelated checks on a brand-new --fresh deployment (OpenSearch ML model not yet active)
- #613 opentr.sh missing from release-manifest.txt while docs instruct operators to run it for restore/rollback
- #614 MINIO_KMS_SECRET_KEY placeholder in .env.example isn't a format MinIO accepts, blocks a truly-fresh cp .env.example .env boot
- #616 fix(docker): docker-compose.backup.yml is not shipped, so the in-app scheduled/S3 backup has no mounted destination in production
- #617 Release rehearsal: dbs_diff_fingerprints() unguarded under set -e silently truncates phases 15-18
- #618 Release rehearsal: unguarded curl to frontend under set -e silently kills phase 16→17→18 (same class as #617)
- #619 fix(release-tests): test-upgrade.sh F-4 (media_file digest) and phase-06b backup-content-diff race async DB writes — same class as #617's Layer 1
- #620 fix(security,testing): post-rehearsal adversarial review findings (8 items, 1 HIGH)
- #622 fix(backend): detect_speaker_attributes and redaction_detect_task have no Task DB record
- #629 task(testing): automatic, signature-scoped cleanup of orphaned e2e/test data across ALL leak classes
- #630 task(testing): run-dev-tests.sh should dynamically start/stop auth-overlay containers (Keycloak, LDAP, etc.) like it does mock-llm
- #640 setup-opentranscribe.sh doesn't read release-manifest.txt — fresh installs never get docker-compose.blackwell.yml or docker-compose.backup.yml despite the manifest's own header claiming it's a consumer
- #52 Feature: AI Interactive Chat with RAG System for Selected Transcripts
- #78 Feature: Admin-Controlled Prompt Sharing System
- #136 [Tip] Example AI summary for Q&A panel
- #359 chat: per-conversation max_tokens and top_p
- #360 chat: projects with pinned scope and project-level prompts
- #383 feat(chat): corpus-scale RAG — summary tier, query routing, aggregation, model-tier parity, and a real eval harness
- #384 fix(chat): sources frame is sent before the excerpt budget is known — UI can show citations the model never saw
- #385 fix(chat): tag-scoped chat silently excludes shared files (tag scope is owner-only, collection scope is not)
- #386 fix(chat): history_max_turns counts pairs in one place and messages in another, halving conversation depth
- #387 fix(chat): first excerpt is always emitted even when it alone exceeds the prompt budget
- #403 feat(rag): master orchestrator — ordered end-to-end implementation of corpus-scale RAG, retrieval tuning, and documents (#383 → #363 → #362)
- #438 fix(chat): an unscoped conversation searches nothing — file_uuids defaults to [] (match nothing), not None (all accessible)
- #439 fix(chat): Gemma reasoning and a raw <channel|> control token leak into the user-visible answer
- #448 Backlog: multilingual RAG/chat — CJK transcripts produce one un-chunked blob (English-only is the current scope)
- #453 Multilingual RAG and chat: four independent stages, none of them a setting
- #461 RAG retrieval quality: what is measured, what is not, and what to do next
- #463 eval: measure whether chat answers are actually useful — QMSum reference answers are already on disk and unused
- #465 AI summaries are displayed and exported completely unmasked, ignoring the user's redaction policy
- #495 RAG eval harness: synthetic corpus injection indexes no chunks on re-injection (test xfailed)
- #514 Live query-trace panel: an animated, Redis-pushed execution tree for search and RAG
- #515 Umbrella: RAG/chat/search/document-ingest completion — status, plan corrections, and open decisions
- #517 eval: scope coverage — the metric no framework measures, and the bug it hides
- #518 eval: calibrate the LLM judge with Cohen's Kappa before tuning anything on it
- #519 eval: acceptance suite for the four real query shapes, over AMI ground truth
- #521 eval: add ELITR-Bench (CC-BY-4.0) — first benchmark that tests speaker attribution directly
- #524 RAG: the speaker axis silently disables itself at corpus scale (roster cap declines wholesale)
- #525 RAG: widening the candidate pool changes nothing — ranking keeps selecting content-free fragments
- #530 RAG: calibrate the answer judge with Cohen's Kappa (gates every quality claim)
- #531 RAG: shipped 48/12/4 retrieval budget starves the chat — 2x recall available
- #533 LLM settings: discover a model's context window instead of defaulting to 8192
- #534 RAG: validate the budget finding on a second corpus (ELITR-Bench) before changing defaults
- #535 RAG: standing acceptance suite over the four query shapes
- #536 chat: base rules leak prompt-internal block vocabulary into answers when the block is absent
- #589 bug(services): group_batch_by_topics miscounts a collection collision as a creation
- #595 test(release-tests): lite-mode rehearsal chat-summary text comes back empty despite citations succeeding
- #611 Lite-mode rehearsal: chat SSE stream sends the model's real answer inside an event: error frame's 'code' field
- #363 search: measure RRF vs score-based hybrid fusion, and record the speaker-turn chunking decision
- #400 fix(search): re-running search indexing never deletes existing chunks — stale tail chunks survive a shorter re-chunk
- #401 fix(search): ingest pipeline recreation compares only model_id — a field_map change is silently ignored on upgrade
- #402 chore(docs): four doc-drift fixes found during the #383/#363 second-opinion review
- #405 fix(search): speaker and title renames never propagate to transcript_chunks — chat speaker scope, search facets, and citations serve stale names until a full reindex
- #432 fix(search): six more display_name writers still leave stale speaker names in transcript_chunks
- #433 fix: ORDER BY start_time is not a total order — re-indexing the same transcript yields different chunks
- #435 fix(search): chunk-prune count gate reads the searcher, so a re-index inside the refresh window leaks orphans permanently
- #436 fix(search): indexing workers have no nltk_data mount — every production chunk was cut by the regex fallback
- #437 fix(search): switching the embedding model silently leaves a mixed-vector index, and embedding_model records the mode not the model
- #449 Chunk boundaries depend on whether NLTK punkt loaded — and on a 5-minute global cooldown
- #501 Bulk indexing fails intermittently: ML Commons circuit breaker false-trips on young-gen garbage
- #502 Offline embedding-model registration is broken on OpenSearch 3.4 (400 'model config is null')
- #503 Verify at setup that the selected embedding model actually works, and size heap per machine
- #504 Embedding model registry offered paraphrase-multilingual-mpnet-base-v2, which OpenSearch does not provide
- #540 OpenSearch startup maintenance: probe the kNN plane and self-heal — vector corruption survives restarts silently
- #542 Dead ANN branch in opensearch_service/transcripts.py::search_transcripts would 400 if ever called
- #606 Semantic search fails to find the obvious gold file for 'space exploration' query, surfaces both anti-gold files instead
- #625 fix(search): neural-search bootstrap is one-shot with no retry, can permanently lose model deployment on a cold OpenSearch boot
- #626 task(search): operator-triggered re-embed for files indexed during a neural-search degraded window
- #638 Offline model registration (file://) is dead in every deployment mode: missing opensearch-ml volume mount + missing config.json
- #188 [BUG] LDAP cn not parsed correctly
- #262 Post-0.5.0 hardening follow-ups from the cloud-seams security review
- #284 Improvements & Security Review
- #296 docs(redaction): redaction_task.py docstring claims unconditional detection — dispatch is actually gated
- #300 bug(asr): AWS access_key_id is dropped when building the provider for a job (test-connection passes, transcription doesn't)
- #324 security: six remaining fail-open paths deferred from #284 Phase 3B
- #353 [BUG] Generic OIDC / Authentik does not work because OpenTranscribe hardcodes Keycloak realm URLs
- #354 [FEATURE] Disable self-registration via environment variable
- #441 JWT algorithm decision is duplicated 3x with different gates; issuers and verifiers disagree
- #442 GDPR Art. 17: no erasure ledger, legal-hold data never re-erased, backup restore resurrects subjects
- #443 Audit log: split user_id into actor and target (schema change, not a convention)
- #444 chat_completion — the production LLM path — has no SSRF validation at all
- #471 Replace gender-guesser (GPLv3) with a permissively-licensed alternative
- #473 Compile a minimal, license-confirmed FFmpeg.wasm core (replace generic @ffmpeg/core CDN fetch)
- #484 directory_sync (LDAP deprovisioning sweep) has no admin settings endpoint — unreachable in any real deployment
- #497 Cross-tenant authorization gap: update_comment and delete_comment run no tenant check
- #498 Five PKI revocation settings are writable in the Settings UI and read by nothing
- #499 PII masking misses names spaCy labels ORGANIZATION, which the default policy excludes
- #513 perf(redaction): ONNX-convert toxic-bert and the search embedding model (and why Presidio should stay in Python)
- #573 docs(compliance): FIPS_140_3_COMPLIANCE.md claims 'FIPS 140-3 compliant' but only implements FIPS-approved algorithms, not a validated module
- #575 docs(compliance): password policy (forced expiry + composition rules) contradicts current NIST SP 800-63B Rev. 4, not FedRAMP IA-5 best practice
- #582 SCIM PUT does not implement RFC 7644 replace semantics
- #587 test(services): AutoLabelService tenancy-scoping and per-user cache paths are untested
- #588 fix(auth): viewer-permission users can reprocess/summarize shared files via API
- #593 PKI E2E admin-cert fixture collides with super_admin email-link protection
- #594 ASR UserASRSettings.base_url is validated and persisted but never consumed — wiring it needs an SSRF guard first
- #615 PKI_TRUSTED_PROXIES default CIDR doesn't cover the full range Docker can assign to a compose network (breaks mTLS header trust under --fresh)
- #623 fix(frontend): PKI/proxy trusted-CIDR admin UI still suggests the now-fixed vulnerable range
- #632 Session accumulation: refresh_token rows for one user hit 272x the configured max_concurrent_sessions limit
- #633 refresh_token rows accumulate unbounded on admin@example.com (5,504+ observed)
- #512 feat(speakers): cross-file speaker clustering — ANN index over speaker embeddings + batch re-resolution
- #543 SpeakerProfile.predicted_gender is written but never read — confirming a gender on a member-less profile is silently invisible
- #603 Speaker confirm-gender/merge don't propagate to other open tabs (cosmetic, self-correcting on reload)
- #605 Live speaker chunk-index label drifts from canonical_speaker_label() resolver (speaker_id=74070)
v0.6.0
Answer quality and interface polishIn progressMake what already ships correct — grounded answers, searchable summaries, an interface pass, and the fixes that affect running deployments today.
30 issues
- #569 feat(frontend): wire persistent download notifications into the live notification bell
- #570 feat(admin): expose locked-account management (view/reset) in the admin UI
- #576 feat(admin): quarantine/takedown has no UI — admin must curl 3 backend-only endpoints
- #649 Audit other interactive UI paths for the same premature-interaction timing bug class as #645
- #682 fix(frontend): UI bug backlog for the v0.6.0 UI refresh (filters, modal styling, button states)
- #644 Admin LLM provider setup: surface discoverable local base URLs instead of requiring manual Docker hostname entry
- #655 bug(docker): diar-native sidecar is unwired in gpu-scale, gpu-split, lite, offline, Windows, --fresh and CPU-only topologies
- #662 bug(config): .env.example ships DIAR_NATIVE_GPU=0, restoring the bare-device-0 pin the compose comment exists to prevent
- #665 fix(gpu): overlap-diarization gate keys off the configured backend, not sidecar reachability — transcriber is never released on the PyAnnote fallback path
- #671 docs(backend): transcription/ and services/diarization/ CLAUDE.md still describe PyAnnote as the engine
- #672 bug(config): PYANNOTE_MODEL means two different things, the admin panel misreports the diarizer, and four diarizer symbols are dead
- #631 Celery prefork pool death spiral: 10h46m of forked children failing to signal UP, root cause unknown
- #680 bug(docker): the published arm64 backend image is not equivalent to amd64 — 765 MB vs 4,454 MB, dependency layer 8.4x smaller
- #681 bug(ci-cd): an unscannable component yields "All security scans completed successfully!" — docs is already in this state
- #683 [BUG] Can't install due to "❌ Failed to download release-manifest.txt from v0.4.1" - 404: Not Found
- #462 feat(search): make AI summaries searchable and citable in the search page
- #464 feat(rag-chat): use LLM summaries as the map output when an LLM is configured (tiered tree_summarize)
- #506 task(rag-chat): measure dropping the stemmed BM25 leg for non-English queries (deferred from #453)
- #523 task(rag-chat): short speaker turns become content-free chunks — route speaker questions, expand context at read time
- #526 task(rag-chat): context expansion decouples citations from their source chunk (snippet longer than the chunk it cites)
- #532 task(rag-chat): retrieval offers 99% of scope but the answer cites 75% — synthesis, not retrieval
- #627 fix(search): admin "Reindex all" only re-indexes the admin's own files, not the whole corpus
- #658 bug(operations): speaker voiceprints live only in OpenSearch and no backup covers them
- #666 fix(search): a transcript text edit never reindexes OpenSearch — search, RAG retrieval and citations serve pre-edit text indefinitely
- #664 fix(security): retention sweep and purge_media_file have no legal_hold guard — a legal-held file can be permanently deleted
- #668 security(deploy): nginx/reverse-proxy hardening — trusted-proxy rate-limit collapse, pre-auth body buffering, missing robots.txt
- #673 fix(redaction): export_locked is enforced only for subtitles — the admin forced-redacted-export policy is bypassable via every other export format
- #676 security(api): LLM connection-test and model-discovery handlers make user-supplied outbound requests with no rate limit
v0.7.0
Documents, speakers, and providersUp nextWiden the library beyond audio, deepen cross-file speaker identity, and add provider breadth.
22 issues
- #516 feat(documents): unified gallery with type filter, uniform status, recovery and takedown parity
- #546 fix(documents): Document.file_hash is written by both ingest paths and read by neither
- #547 fix(documents): watch-imported documents are unrepresentable in the watch-source API (no document_uuid; two statuses missing from the enums)
- #552 task(documents): re-land the document-ingestion vertical from feat/doc-ingestion for v0.6.0
- #562 feat(llm): custom note templates per meeting type (standup/1:1/interview)
- #46 feat(transcript): transcript version control and change tracking
- #559 security(dependencies): evaluate replacing Perl exiftool (16 of 20 CRITICAL CVEs) — ffprobe-only vs exiftool-rs
v0.8.0
Native diarizationLaterRetire the in-process PyTorch diarizer for the native Rust/ONNX engine, including the voiceprint migration it depends on.
10 issues
- #572 task(asr): roadmap for removing PyTorch/PyAnnote diarization once native diar-native has parity
- #639 Diarization backend defaults to native (diar-native sidecar) but the sidecar is never distributed to self-hosted installs — perpetual silent-ish PyAnnote fallback
- #654 task(models): add a download-models diar-native group — the export four files already claim exists
- #656 task(asr): sidecar-unavailable retry policy, bounded timeout and status surface before the PyAnnote fallback is removed
- #657 bug(search): v4 embedding migration loses profile voiceprints and crosses index dimensions mid-run
- #659 feat(search): a real rollback path for the v3→v4 speaker-index alias swap
- #660 task(asr): --lite adopts the diar-native CPU execution provider for speaker embeddings
- #663 docs(legal): add a NOTICE file — the native diarizer's weights are CC-BY-4.0 and still require pyannote attribution
- #669 task(testing): diarization test + gate coverage survives the PyAnnote removal (several would go green measuring nothing)
- #670 bug(deploy): upgrading into a mandatory-sidecar release degrades silently instead of refusing
v0.9.0
Meetings and extensibilityLaterBring meetings in automatically and open the pipeline to external tooling.
v1.0.0
Platform maturityLaterAlternative transcription engines, a desktop application, live transcription, and formal compliance validation.
6 issues
- #283 feat(desktop): cross-platform standalone desktop app (Tauri + SQLite/sqlite-vec + local inference core)
Backlog
Not yet scheduledUnscheduledTracked and grouped, but not assigned to a release. These move into a version as the work ahead of them lands.
1 issue
- #415 security(dependencies): accepted risk — 16 CRITICAL perl CVEs via libimage-exiftool-perl, re-check when Debian ships fixes