# Semantic Contracts: LLM Table Translation Service

**Feature Branch**: `028-llm-datasource-supeset`  
**Date**: 2026-05-17 (updated to match implementation)  
**Protocol**: GRACE-Poly v2.6

---

## Backend Contracts (Python / FastAPI)

### [DEF:TranslatePlugin:Module]
`backend/src/plugins/translate/plugin.py`
@COMPLEXITY 2
@PURPOSE Plugin entry point implementing PluginBase for the translation service. Serves as registration artifact for plugin_loader auto-discovery. All business logic delegated to independent service classes.
@RELATION INHERITS -> [PluginBase:Class]
@RATIONALE Separate plugin avoids bloating LLMAnalysisPlugin beyond fractal limit (<400 lines). C2 because plugin.py is a registration skeleton; all execution logic lives in service classes.
@REJECTED Extending LLMAnalysisPlugin would conflate two distinct feature domains (dashboard validation vs table translation). Executing business logic through PluginBase.execute() was rejected in favor of service-layer architecture for testability and route flexibility.
[/DEF:TranslatePlugin:Module]

### [DEF:TranslationOrchestrator:Class]
`backend/src/plugins/translate/orchestrator.py`
@COMPLEXITY 5
@PURPOSE Central coordinator for translation run lifecycle: validates preconditions, manages preview quality gate, dispatches to executor, generates safe SQL, submits to Superset SQL Lab API, manages retry, records events, enforces retention.
@PRE Job configuration is saved and valid. Superset datasource is accessible. LLM provider is configured and reachable. For manual runs: preview session must be accepted. For scheduled runs: at least one prior successful manual run exists.
@POST TranslationRun created with translation_status and insert_status. INSERT SQL generated (safe dialect) and submitted to Superset `/api/v1/sqllab/execute/`. Superset query reference recorded. Structured events recorded for all lifecycle transitions.
@SIDE_EFFECT Creates TranslationRun, TranslationBatch, TranslationRecord, TranslationEvent, MetricSnapshot rows. Calls LLM provider API (token consumption). Calls Superset SQL Lab API.
@DATA_CONTRACT Input: TranslationJob (config snapshot) + datasource rows → Output: TranslationRun (result) + Superset query reference
@INVARIANT A run must transition through states: pending → running → (completed|partial|failed|cancelled|skipped). insert_status transitions: not_started → (submitted → running → succeeded|failed | skipped). No other state transitions allowed. Snapshot isolation: in-progress runs use config snapshot; config edits affect future runs only.
@RELATION CALLS -> [TranslationPreview:Class]
@RELATION CALLS -> [TranslationExecutor:Class]
@RELATION CALLS -> [SQLGenerator:Class]
@RELATION CALLS -> [SupersetSqlLabExecutor:Class]
@RELATION CALLS -> [TranslationEventLog:Class]
@RELATION CALLS -> [LLMProviderService:Module]
@RELATION CALLS -> [SupersetClient:Module]
@RATIONALE Centralized orchestrator is needed because preview gating, execution, SQL generation, Superset API submission, event logging, and retry share state (run_id, config snapshot) and must coordinate within a single transaction boundary for consistency.
@REJECTED Distributed actor model (Celery tasks per batch) was rejected because it introduces eventual-consistency challenges for run status tracking without proportional benefit at the expected scale. Synchronous batch processing provides simpler debugging and deterministic retry. UPDATE statements are never generated — all modifications use INSERT/UPSERT per PostgreSQL dialect.
[/DEF:TranslationOrchestrator:Class]

### [DEF:TranslateJobService:Class]
`backend/src/plugins/translate/service.py`
@COMPLEXITY 4
@PURPOSE Central service layer for job CRUD, inline corrections with context capture, and bulk find-and-replace operations. Coordinates between routes, dictionary manager, and event log.
@PRE Job configuration is saved and valid. For corrections: run record must exist with translated values.
@POST Job CRUD operations reflected in database. Inline corrections create/update DictionaryEntry with context_data, usage_notes, origin tracking. Bulk find-and-replace updates TranslationLanguage.final_value for matched rows.
@SIDE_EFFECT Creates/updates DictionaryEntry rows. Updates TranslationLanguage.final_value. Logs correction events.
@RELATION CALLS -> [DictionaryManager:Class]
@RELATION CALLS -> [TranslationEventLog:Class]
@RELATION CALLS -> [ContextAwarePromptBuilder:Class]
@RELATION CALLS -> [BulkFindReplaceService:Class]
@RATIONALE C4 warranted because service coordinates multiple domains (jobs, corrections, bulk operations) with stateful side effects and origin tracking.
[/DEF:TranslateJobService:Class]

### [DEF:TranslationPreview:Class]
`backend/src/plugins/translate/preview.py`
@COMPLEXITY 4
@PURPOSE Fetch a configurable sample of source rows (1-100), send to LLM with configured context and per-batch filtered dictionary, return per-language translations side-by-side for quality gate. Creates persistent PreviewSession and PreviewRecord rows. Supports multi-target: single LLM call for ALL target languages.
@PRE Job configuration is saved with target_languages (list, min 1). Datasource is accessible. Sample size configured (default 10, range 1-100).
@POST PreviewSession created with config_hash and dict_snapshot_hash. PreviewRecord rows created with per-language TranslationPreviewLanguage entries. Accepting preview gates full execution. No data persisted to target table. For sample_size >30, cost warning displayed.
@SIDE_EFFECT Calls LLM provider API (token consumption). Creates PreviewSession, PreviewRecord, TranslationPreviewLanguage rows.
@RELATION CALLS -> [LLMProviderService:Module]
@RELATION CALLS -> [SupersetClient:Module]
@RELATION CALLS -> [DictionaryManager:Class]
[/DEF:TranslationPreview:Class]

### [DEF:TranslationExecutor:Class]
`backend/src/plugins/translate/executor.py`
@COMPLEXITY 4
@PURPOSE Process source rows in auto-sized batches through LLM, request translations for ALL target languages in single structured JSON response, parse multi-language results, create per-language TranslationLanguage entries. Features: translation cache via source_hash, preview edit carry-forward, new-key-only filtering, dictionary enforcement post-processing.
@PRE Run exists with translation_status `running`. Source rows fetched. Batch size configured. LLM provider configured.
@POST All processable rows have TranslationRecord + TranslationLanguage entries. Each batch has TranslationBatch record with statistics. Run statistics updated per language via TranslationRunLanguageStats.
@SIDE_EFFECT Calls LLM provider API (token consumption). Creates TranslationBatch, TranslationRecord, TranslationLanguage rows.
@RELATION CALLS -> [LLMProviderService:Module]
@RELATION CALLS -> [DictionaryManager:Class]
@RELATION CALLS -> [ContextAwarePromptBuilder:Class]
[/DEF:TranslationExecutor:Class]

### [DEF:SQLGenerator:Class]
`backend/src/plugins/translate/sql_generator.py`
@COMPLEXITY 3
@PURPOSE Generate safe dialect-appropriate INSERT/UPSERT SQL from TranslationRecord/TranslationLanguage rows, keyed by configured target key columns. Supports PostgreSQL/Greenplum (ON CONFLICT) and ClickHouse (plain INSERT). Pure function — no I/O, no mutation.
@PRE TranslationRecord rows exist with translated/final values. Target table schema validated at configuration time.
@POST Returns a syntactically valid, injection-safe SQL INSERT/UPSERT statement for the detected dialect.
@SIDE_EFFECT None — pure function.
@RELATION CALLS -> [SupersetClient:Module]
@RATIONALE C3 (not C4 as originally planned) because SQLGenerator is a pure function with no state, no I/O, and no external side effects.
[/DEF:SQLGenerator:Class]

### [DEF:SupersetSqlLabExecutor:Class]
`backend/src/plugins/translate/superset_executor.py`
@COMPLEXITY 3
@PURPOSE Submit generated SQL to Superset SQL Lab API `/api/v1/sqllab/execute/` with fallback to `/api/v1/sql_lab/execute/` (underscore variant). Poll `/api/v1/query/{id}` for completion. Supports multiple Superset response formats. Record Superset query reference, status, and error details.
@PRE TranslationRun exists with translation_status completed/partial. SQL is generated and syntactically valid. Superset is accessible.
@POST TranslationRun.insert_status updated (submitted → running → succeeded|failed). Superset query reference, error details, rows_affected stored.
@SIDE_EFFECT Calls Superset API (SQL execution, database write). Updates TranslationRun row.
@RELATION CALLS -> [SupersetClient:Module]
@RELATION CALLS -> [TranslationEventLog:Class]
[/DEF:SupersetSqlLabExecutor:Class]

### [DEF:DictionaryManager:Class]
`backend/src/plugins/translate/dictionary.py`
@COMPLEXITY 4
@PURPOSE CRUD for TerminologyDictionary and DictionaryEntry with language-pair-aware unique constraint `(dictionary_id, source_term_normalized, source_language, target_language)`. CSV/TSV import with conflict detection. Per-batch language-pair-filtered term extraction for LLM prompts.
@PRE Dictionary model exists. User has required permissions.
@POST CRUD operations reflected in database. Filtered term list returned for batch with language-pair matching.
@SIDE_EFFECT Creates/updates/deletes DictionaryEntry rows. May read TranslationRun for origin tracking.
@RELATION CALLS -> [DictionaryEntry:Class]
@RELATION CALLS -> [TranslationJobDictionary:Class]
@RELATION CALLS -> [ContextAwarePromptBuilder:Class]
[/DEF:DictionaryManager:Class]

### [DEF:ContextAwarePromptBuilder:Class]
`backend/src/plugins/translate/prompt_builder.py`
@COMPLEXITY 3
@PURPOSE Construct LLM prompts with context-aware dictionary entries. For entries with has_context=True, render context annotations with format: `"source_term" (context: key=value, ...) → "target_term"`. Compute Jaccard similarity between entry context_data and incoming row context columns to flag priority_context entries (>50% overlap). Cap context rendering at ~500 tokens per entry.
@RELATION DEPENDS_ON -> [DictionaryManager:Class]
@RELATION DEPENDS_ON -> [LLMProviderService:Module]
[/DEF:ContextAwarePromptBuilder:Class]

### [DEF:TranslationScheduler:Class]
`backend/src/plugins/translate/scheduler.py`
@COMPLEXITY 4
@PURPOSE Manage translation job schedules with timezone and concurrency policy support: create/update/delete, register with APScheduler, handle trigger dispatch with skip/queue, enforce new-key-only strategy with baseline_expired fallback (>90 days), failure notification dispatch.
@PRE SchedulerService is running. Job has configuration. For execution bypass: at least one prior successful manual run exists.
@POST Schedule registered with APScheduler or removed. On trigger: new TranslationRun created with trigger_type=scheduled. New-key-only filter applied. On failure: NotificationService called. Schedule remains enabled.
@SIDE_EFFECT Creates TranslationRun rows. Calls SchedulerService. Emits schedule_triggered/skipped/failed events.
@RELATION CALLS -> [SchedulerService:Class]
@RELATION CALLS -> [TranslationOrchestrator:Class]
@RELATION CALLS -> [TranslationEventLog:Class]
@RELATION CALLS -> [NotificationService:Module]
[/DEF:TranslationScheduler:Class]

### [DEF:TranslationEventLog:Class]
`backend/src/plugins/translate/events.py`
@COMPLEXITY 5
@PURPOSE Structured event logging: write immutable events, enforce invariants (exactly one run_started + one terminal event per run), query for audit/dashboard, enforce 90-day retention pruning with MetricSnapshot persistence before deletion.
@PRE TranslationEvent table exists. Event type recognized from VALID_EVENT_TYPES. For run-scoped events: run exists.
@POST Event row created with type-specific payload. Pruning job persists MetricSnapshot, then removes events/records older than 90 days.
@SIDE_EFFECT Creates TranslationEvent rows. Creates MetricSnapshot rows at pruning time. Deletes expired rows.
@DATA_CONTRACT Input: (run_id?, job_id, event_type, payload: dict) → Output: TranslationEvent
@INVARIANT Every created run MUST have exactly one run_started event and exactly one terminal event among: run_succeeded, run_partial, run_failed, run_cancelled, run_skipped. Events are immutable after creation. Cumulative metrics survive pruning via MetricSnapshot.
@RELATION CALLS -> [TranslationEvent:Class]
@RELATION CALLS -> [MetricSnapshot:Class]
@RATIONALE C5 warranted: event log is single source of truth for observability, metrics, and audit. Immutability, retention, and metric continuity invariants must be enforced to prevent data loss or tampering.
@REJECTED stdout-only logging lacks structured payload integrity and cannot enforce terminal-event invariant. Event-sourced metrics without snapshots would lose cumulative data after pruning.
[/DEF:TranslationEventLog:Class]

### [DEF:TranslationMetrics:Class]
`backend/src/plugins/translate/metrics.py`
@COMPLEXITY 3
@PURPOSE Aggregate per-job metrics from live TranslationEvent log AND persistent MetricSnapshot table. For recent data (<90 days): compute from events. For cumulative totals: read latest MetricSnapshot + recent events. Includes per-language breakdown from per_language_metrics JSON.
@RELATION CALLS -> [TranslationEventLog:Class]
@RELATION CALLS -> [MetricSnapshot:Class]
[/DEF:TranslationMetrics:Class]

### [DEF:TranslateRoutes:Package]
`backend/src/api/routes/translate/`
@COMPLEXITY 4
@PURPOSE FastAPI route handlers organized as package with 11 sub-modules: job CRUD (249 строк), run execution (554), run list (225), preview (194), dictionary (391), correction (100), schedule (239), metrics (65), helpers (71). All endpoints enforce RBAC per access-control matrix. Runs execute in background threads with isolated DB sessions.
@RELATION CALLS -> [TranslationOrchestrator:Class]
@RELATION CALLS -> [TranslateJobService:Class]
@RELATION CALLS -> [DictionaryManager:Class]
@RELATION CALLS -> [TranslationScheduler:Class]
@RELATION CALLS -> [TranslationEventLog:Class]
@RELATION CALLS -> [TranslationMetrics:Class]
@RELATION BINDS_TO -> [PermissionChecker:Dependency]
@RATIONALE C4 because routes package spans 11 files, coordinates 6+ service dependencies, and enforces RBAC across 13 permission strings. Split into sub-modules by domain to respect fractal limit (<400 lines per file, except _run_routes.py at 554).
@REJECTED Single translate.py file rejected — would exceed fractal limit at 2 141 lines. Multiple route files with shared state would couple domains.
[/DEF:TranslateRoutes:Package]

### [DEF:TranslateModels:Module]
`backend/src/models/translate.py`
@COMPLEXITY 2
@PURPOSE 15 SQLAlchemy ORM models: TranslationJob, TranslationRun, TranslationBatch, TranslationRecord, TranslationLanguage, TranslationEvent, TranslationPreviewSession, TranslationPreviewRecord, TranslationPreviewLanguage, TerminologyDictionary, DictionaryEntry, TranslationJobDictionary, TranslationSchedule, MetricSnapshot, TranslationRunLanguageStats.
[/DEF:TranslateModels:Module]

### [DEF:TranslateSchemas:Module]
`backend/src/schemas/translate.py`
@COMPLEXITY 2
@PURPOSE 35+ Pydantic v2 request/response schemas for translation API endpoints including multi-language, context-aware, and bulk operations.
[/DEF:TranslateSchemas:Module]

### [DEF:BulkFindReplaceService:Class]
`backend/src/plugins/translate/service.py` (extended)
@COMPLEXITY 3
@PURPOSE Apply find-and-replace across translated values in a completed run. Supports regex or literal patterns, filtered by target language. Generates preview of affected rows before atomic apply. Optionally submits corrections to dictionary with context capture.
@PRE Run must be completed. Pattern must be valid regex (if regex flag set).
@POST All matching cells updated. Optional dictionary entries created with context_source="bulk".
@SIDE_EFFECT Updates TranslationLanguage.final_value. Optionally creates DictionaryEntry rows.
@RELATION DEPENDS_ON -> [InlineCorrectionService:Class]
[/DEF:BulkFindReplaceService:Class]

---

## Frontend Contracts (Svelte 5 / SvelteKit)

### [DEF:TranslateJobList:Component]
`frontend/src/routes/translate/+page.svelte`
@COMPLEXITY 3
@PURPOSE SvelteKit page listing all translation jobs with status/schedule indicators, target languages as badges, create/duplicate/delete actions.
@UX_STATE idle, loading, empty, populated, error
[/DEF:TranslateJobList:Component]

### [DEF:TranslationJobConfig:Component]
`frontend/src/routes/translate/[id]/+page.svelte`
@COMPLEXITY 4
@PURPOSE Tabbed page with Configuration, Preview, Run, and Schedule sections. Multi-language target selection, datasource column mapping, composite key support, LLM provider/dictionary attachment with priority ordering, sample size slider (1-100), inline correction, bulk find-replace.
@UX_STATE idle, loading, configured, saving, validation_error, datasource_unavailable
@UX_REACTIVITY Column list $derived from datasource; dictionary list filtered by target_language; per-language columns in preview/run results
@UX_FEEDBACK Cost warning at sample size >30; per-language statistics on run completion
[/DEF:TranslationJobConfig:Component]

### [DEF:TranslationPreview:Component]
`frontend/src/lib/components/translate/TranslationPreview.svelte`
@COMPLEXITY 4
@PURPOSE Side-by-side per-language preview of source rows with LLM translations, per-language approve/edit/reject, bulk approve, configurable sample size slider, cost estimate card, carry-forward edits to full run.
@UX_STATE idle, loading, preview_loaded, preview_error, accepted, rejected, stale_config
@UX_FEEDBACK Spinner during LLM call; visual distinction for LLM-generated vs user-edited vs "und" warning
@UX_RECOVERY Retry preview; re-fetch with updated config; individual row re-translate
[/DEF:TranslationPreview:Component]

### [DEF:TranslationRunProgress:Component]
`frontend/src/lib/components/translate/TranslationRunProgress.svelte`
@COMPLEXITY 4
@PURPOSE Live progress display: progress bar, per-language batch counter, success/failure counts, cancel button. WebSocket-driven for real-time updates.
@UX_STATE idle, running, cancelling, cancelled, completed, partial, failed, insert_pending, insert_running, insert_failed
@UX_FEEDBACK Per-language progress $derived; real-time batch/insert status
@UX_RECOVERY Retry failed batches; cancel run; download skipped rows as CSV
[/DEF:TranslationRunProgress:Component]

### [DEF:TranslationRunResult:Component]
`frontend/src/lib/components/translate/TranslationRunResult.svelte`
@COMPLEXITY 4
@PURPOSE Completion summary with per-language statistics, Superset execution status/reference, generated SQL (audit/debug), inline feedback-loop correction controls.
@UX_STATE completed, partial, failed, insert_failed
@UX_FEEDBACK Superset execution status badge; per-language statistics section; SQL block for audit
@UX_RECOVERY Retry failed rows; retry insert; submit corrections; bulk find & replace
@RELATION CALLS -> [TermCorrectionPopup:Component]
@RELATION CALLS -> [CorrectionCell:Component]
[/DEF:TranslationRunResult:Component]

### [DEF:CorrectionCell:Component]
`frontend/src/lib/components/translate/CorrectionCell.svelte`
@COMPLEXITY 3
@PURPOSE Inline-editable cell for translation results. Click to edit, shows "Submit to Dictionary" button after edit. Auto-fills language pair from row metadata. Supports context capture and usage notes.
@UX_STATE view, editing, submitting, submitted, error
@UX_FEEDBACK Toast on submit success/error; "Dictionary ✓" badge on corrected rows
@UX_RECOVERY Retry button on submit failure; edit persists locally
@RELATION DEPENDS_ON -> [TranslateApiClient:Module]
@RELATION BINDS_TO -> [translateStore:Store]
[/DEF:CorrectionCell:Component]

### [DEF:BulkReplaceModal:Component]
`frontend/src/lib/components/translate/BulkReplaceModal.svelte`
@COMPLEXITY 3
@PURPOSE Modal for bulk find-and-replace across translated values. Pattern input (regex toggle), target language selection, preview table with "N rows affected", apply with confirmation. Optional "Submit to dictionary with context" with usage notes.
@UX_STATE closed, configuring, previewing, applying, applied, error
@UX_FEEDBACK Preview table showing before/after; counter of affected rows; warning at >50 rows
@UX_REACTIVITY Preview list $derived from pattern + run data
@RELATION DEPENDS_ON -> [TranslateApiClient:Module]
[/DEF:BulkReplaceModal:Component]

### [DEF:TermCorrectionPopup:Component]
`frontend/src/lib/components/translate/TermCorrectionPopup.svelte`
@COMPLEXITY 3
@PURPOSE Popup for submitting corrections: source term (pre-filled), incorrect translation, corrected translation, source language (auto), target language (auto), dictionary selector (filtered by language pair), context_data preview (editable/removable), usage notes textarea. Conflict dialog (overwrite/keep/cancel).
@UX_STATE closed, selecting, editing, submitting, conflict_detected, submitted
[/DEF:TermCorrectionPopup:Component]

### [DEF:BulkCorrectionSidebar:Component]
`frontend/src/lib/components/translate/BulkCorrectionSidebar.svelte`
@COMPLEXITY 3
@PURPOSE Sidebar for bulk correction: collect multiple selected terms across rows, per-term correction inputs, submit all to dictionary atomically.
@UX_STATE closed, collecting, reviewing, submitting, submitted
@UX_REACTIVITY Selected terms list $state
[/DEF:BulkCorrectionSidebar:Component]

### [DEF:ScheduleConfig:Component]
`frontend/src/lib/components/translate/ScheduleConfig.svelte`
@COMPLEXITY 3
@PURPOSE Schedule panel: type selector (cron/interval/once), cron expression with validation, interval input, timezone selector, next-3-executions preview, concurrency policy (skip/queue), enable/disable toggle. Warns if no prior successful manual run.
@UX_STATE idle, editing, validating, enabled, disabled, no_prior_run_warning
@UX_REACTIVITY Next execution times $derived with timezone display
[/DEF:ScheduleConfig:Component]

### [DEF:DictionaryEditor:Component]
`frontend/src/routes/translate/dictionaries/[id]/+page.svelte`
@COMPLEXITY 3
@PURPOSE Inline term editor with per-row language pair: add/edit/delete entries, CSV/TSV import with conflict preview (overwrite/keep), export, context_data + usage_notes display in expandable rows, context_source badges.
@UX_STATE idle, loading, editing, importing, import_preview, import_conflict, saving
[/DEF:DictionaryEditor:Component]

### [DEF:DictionaryList:Component]
`frontend/src/routes/translate/dictionaries/+page.svelte`
@COMPLEXITY 3
@PURPOSE SvelteKit page listing dictionaries with name, term count, attached job count, create/delete actions. Blocks deletion of attached dictionaries.
@UX_STATE idle, loading, empty, populated, delete_blocked
[/DEF:DictionaryList:Component]

### [DEF:TranslationHistory:Component]
`frontend/src/routes/translate/history/+page.svelte`
@COMPLEXITY 3
@PURPOSE Filterable run history: datasource, target table, per-language row counts, translation_status, insert_status, date, user. Detail view with config snapshot, prompt, per-language translations with edit marks, INSERT SQL, Superset execution reference. Pruned runs show metadata only with "data unavailable" markers.
@UX_STATE idle, loading, empty, populated, detail_open, pruned
[/DEF:TranslationHistory:Component]

### [DEF:TranslationMetricsDashboard:Component]
`frontend/src/lib/components/translate/TranslationMetricsDashboard.svelte`
@COMPLEXITY 2
@PURPOSE Admin dashboard displaying per-job metrics: run counts, success/failure ratio, cumulative tokens, cumulative cost, average latency, per-language breakdown.
@UX_STATE idle, loading, populated, error
[/DEF:TranslationMetricsDashboard:Component]

### [DEF:TranslationRunGlobalIndicator:Component]
`frontend/src/lib/components/translate/TranslationRunGlobalIndicator.svelte`
@COMPLEXITY 2
@PURPOSE Global indicator showing active translation runs with progress. Polls or WebSocket-driven.
@UX_STATE hidden, active, completed
[/DEF:TranslationRunGlobalIndicator:Component]

### [DEF:TranslateApiClient:Module]
`frontend/src/lib/api/translate.js`
@COMPLEXITY 2
@PURPOSE API client wrapping requestApi/fetchApi for all translate endpoints: jobs, runs, preview, dictionaries, entries, corrections, schedules, metrics, bulk replace.
[/DEF:TranslateApiClient:Module]

### [DEF:translateStore:Store]
`frontend/src/lib/stores/translationRun.js`
@COMPLEXITY 3
@PURPOSE Svelte 5 rune store for translation feature state: run progress, WebSocket connection status, per-language progress.
@RELATION BINDS_TO -> [TranslateApiClient:Module]
@RELATION BINDS_TO -> [TaskWebSocket:Module]
[/DEF:translateStore:Store]

---

## Integration Contracts (Existing System — Reused)

| Contract ID | What It Provides | How Translation Uses It |
|-------------|-----------------|------------------------|
| `[LLMProviderService:Module]` | LLM API call with provider selection, key encryption, retry/fallback | Sends batches with constructed prompts; receives structured JSON translations for all target languages |
| `[SupersetClient:Module]` | Superset API: datasource schema, SQL Lab execution, column metadata | Fetch column metadata, submit SQL to `/api/v1/sqllab/execute/`, poll status |
| `[SchedulerService:Class]` | APScheduler lifecycle, add_job/remove_job, cron/interval/date triggers | Translation schedules registered as APScheduler jobs; load_schedules discovers active TranslationSchedule rows |
| `[NotificationService:Module]` | Email/Telegram/Slack notification dispatch | Scheduled run failure notifications with job name, failure reason, run link |
| `[PermissionChecker:Dependency]` | FastAPI dependency for RBAC enforcement with ownership scoping | Route handlers annotated per 13-permission access-control matrix |
| `[TaskWebSocket:Module]` | WebSocket for real-time task progress streaming | Translation run progress events (per-language) streamed to frontend store |
| `[TaskContext:Class]` | Background task lifecycle context with structured logging | Orchestrator runs as async background task with source-tagged log entries |

---

## Updated Contracts (2026-05-17 — aligned with implementation)

### [DEF:TranslationLanguage:Class]
`backend/src/models/translate.py`
@COMPLEXITY 1
@PURPOSE Per-language translation storage for a TranslationRecord. One row per (record_id, language_code). Fields: language_code, source_language_detected (BCP-47), translated_value, user_edit, final_value, status.
@RELATION DEPENDS_ON -> [TranslationRecord:Class]
[/DEF:TranslationLanguage:Class]

### [DEF:TranslationPreviewLanguage:Class]
`backend/src/models/translate.py`
@COMPLEXITY 1
@PURPOSE Per-language preview results. Mirrors TranslationLanguage structure for preview records.
@RELATION DEPENDS_ON -> [TranslationPreviewRecord:Class]
[/DEF:TranslationPreviewLanguage:Class]

### [DEF:TranslationRunLanguageStats:Class]
`backend/src/models/translate.py`
@COMPLEXITY 1
@PURPOSE Per-language statistics for a translation run: total_rows, translated_rows, failed_rows, skipped_rows, token_count, estimated_cost per language_code.
@RELATION DEPENDS_ON -> [TranslationRun:Class]
[/DEF:TranslationRunLanguageStats:Class]
