Backend: - tiers.py: real license validation via Heimdall (self-hosted key or cloud user_id), 30-min cache, BYOK exception for translation - session_store.py: create_session() accepts tier/user_id/window_ms/transcribe_lang/ num_speakers; tier-aware _should_reap() (Free: reap on subscriber leave, Paid: activity TTL); auto-snapshot paid sessions with history on reap; voice-ready probe on session start - services/translator.py: DeepL-backed label translation, CF-managed and BYOK key paths, per-session label cache - models/session.py, scene_event.py, service_event.py: new event types and session fields - api/snapshots.py: GET /sessions/history + POST /session/resume (Paid tier only) - api/dev.py: dev-only /dev/voice/stop|start|restart proxy to cf-orch agent - migrations/002_session_snapshots.sql: session_snapshots table Frontend: - ComposeBar.vue: pre-session settings panel (window, language, speakers, Elcor toggle) with slide transition; passes options to startSession() - stores/settings.ts: persistent user preferences (localStorage), survives page reload - stores/session.ts: voiceReady/voiceError/voiceWarning states; SceneEvent/AccentEvent/ ServiceEvent types; TTL timers for environ/queue badges; startSession() accepts opts - composables/useToneStream.ts: handlers for scene-event, accent-event, service-event SSE - NowPanel.vue: diarization speaker identity badge, acoustic scene badge, privacy risk indicator - HistoryStrip.vue: per-speaker colour chips in history strip - components/DevPanel.vue: dev-only cf-voice stop/restart controls + thread view toggle - App.vue: DevPanel in footer (DEV only), threadView flag switches v0.1.x/v0.2.x preview Tests: - tests/test_pinning.py: 20 tests covering tier-aware reaping, snapshot creation, and translator behaviour - tests/test_tiers.py: 17 tests covering key validation, cloud resolution, caching, require_paid() gate, BYOK exception - All 72 tests passing
21 lines
1.2 KiB
SQL
21 lines
1.2 KiB
SQL
-- Migration 002: Session snapshots for Paid tier session pinning.
|
|
-- When a Paid session ends, its annotation history is saved here so the user
|
|
-- can resume it in a later session. Snapshots contain annotation metadata only —
|
|
-- no audio, no raw transcription text unless the user has opted in to STT retention.
|
|
--
|
|
-- Privacy: user_id scopes snapshots to the authenticated user. For self-hosted
|
|
-- installs with no cloud auth, user_id is an empty string (instance-shared).
|
|
|
|
CREATE TABLE IF NOT EXISTS session_snapshots (
|
|
id TEXT PRIMARY KEY, -- UUID
|
|
user_id TEXT NOT NULL DEFAULT '', -- cf_user from cloud mode; '' for self-hosted
|
|
session_id TEXT NOT NULL, -- original session_id (short 8-char)
|
|
created_at REAL NOT NULL, -- Unix epoch (time.time())
|
|
ended_at REAL NOT NULL, -- Unix epoch
|
|
elcor INTEGER NOT NULL DEFAULT 0, -- 1 = Elcor subtext mode was active
|
|
event_count INTEGER NOT NULL DEFAULT 0,
|
|
events_json TEXT NOT NULL DEFAULT '[]' -- JSON array of ToneEvent dicts
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_snapshots_user_time
|
|
ON session_snapshots (user_id, ended_at DESC);
|