The Trinity Beast — TBTS Data Dictionary

Complete schema reference for the Trinity Beast Translation Service — 9 tables, 197 columns: jobs and quotes, the 127-language catalog, per-language tuning, the parameter store, model catalog and task orchestration.

Database: CPMP_Backend_Aurora Engine: Aurora PostgreSQL Serverless v2 Updated: October 10, 2026 Version: v2

Table of Contents

  1. Translation Engine Tables
    1. 1. translation_jobs — Translation job orchestration (36 columns)
    2. 2. translation_job_events — Translation job audit log (8 columns)
    3. 3. translation_quotes — Customer quotes, payment, requotes and refunds (61 columns)
    4. 4. translation_parameters — Cost, pricing, refund and operational parameters (6 columns)
    5. 5. bedrock_model_catalog — Multi-provider Bedrock model registry (12 columns)
    6. 6. translation_tasks — Task Organizer parent-child orchestration (16 columns)
    7. 7. translation_language_profiles — Per-language tuning with auto-tuning (18 columns, 127 rows)
    8. 8. translation_supported_languages — The 127-language catalog (17 columns)
    9. 9. translation_chunk_telemetry — Per-chunk translation metrics (23 columns)
  2. Reference
    1. Entity Relationships
    2. Valkey Cache Keys
    3. Admin API Endpoints

List of Diagrams

1. translation_jobs

Purpose: Translation job orchestration. Every batch of work the engine runs is a row here: the documents, the languages, the agent, the progress and the cost. A customer's paid quote becomes one parent job, and its one free retry becomes a second job pointing at the same quote, so the whole story of a purchase is two joins away.

36 columns

ColumnData TypeDefaultNullableDescription
id PKuuidgen_random_uuid()NOInternal UUID, generated by the database
job_idvarchar(64)—NOPublic job identifier, unique, used in every API response: 12 hex digits, a hyphen and 16 more (e.g., 019e4b8a37bc-1f2e3d4c5b6a7980)
statevarchar(20)queuedNOJob state: queued, running, finalizing, succeeded, partial, failed, cancelled. There is no completed state; a fully delivered job is succeeded.
submitted_attimestamptznow()NOWhen the job was submitted
started_attimestamptz—YESWhen processing began
completed_attimestamptz—YESWhen the job reached a terminal state
submitted_byvarchar(50)admin-apiYESWhich path created the job, e.g. admin-api (direct submission), retry-failed (admin retry) or retry-customer (a customer's free retry)
docsjsonb—NOArray of document names in this job
langsjsonb—NOArray of target language codes, each already resolved through the 127-language catalog
optionsjsonb{}YESJob options (chunk-size overrides, skip_validation, routing). A retry inherits its parent's options.
progressjsonb{}YESPer-pair progress snapshot
errorsjsonb[]YESError details for failed pairs
bedrock_cost_usdnumeric(8,4)0YESTotal Bedrock cost of this job in USD
bedrock_invocationsinteger0YESBedrock calls counted from successful pairs
total_chunksinteger0YESDocument chunks processed
total_pairsinteger0YESDocument-language pairs in this job
succeeded_pairsinteger0YESPairs delivered
failed_pairsinteger0YESPairs that failed
elapsed_secondsinteger—YESWall-clock duration in seconds
step_function_arntext—YESLegacy. The Step Functions pipeline was retired on June 27, 2026, so new jobs leave this empty.
retry_ofvarchar(64)—YESjob_id of the job this one retries
idempotency_keyvarchar(128)—YESClient-provided idempotency key
cloudfront_invalidation_idsjsonb[]YESCloudFront invalidations issued for library documents
search_index_rebuiltbooleanfalseYESWhether the search index was rebuilt after this job
notification_sentbooleanfalseYESWhether the completion notice went out (prevents a second email)
created_attimestamptznow()NORow creation time
updated_attimestamptznow()NOLast change
reasontext—YESCancellation or failure reason
modelvarchar(50)claude-sonnet-4.6YESThe agent for the whole job (qwen3-235b, deepseek-v3, mistral-large, claude-haiku-5.5, claude-sonnet-4.6, claude-opus-4.8), or per-language when each language has its own agent. The column default is a legacy value: an admin retry now writes the original job's model, and a customer's free retry runs on the agent stored on the quote.
execution_modevarchar(30)realtimeYESrealtime or batch
s3_input_uritext—YESBatch inference input location
s3_output_uritext—YESBatch inference output location
task_idvarchar(48)NULLYESParent task in the Task Organizer (translation_tasks.task_id). NULL for a standalone job.
cancelled_bytext—YESWho or what cancelled the job. enqueue-failed marks a job whose queue messages never went out, so it never started.
quote_idvarchar(64)—YESThe customer quote this job serves, set on the parent job and on its free retry. NULL for internal jobs. Backfilled by the migration for existing jobs.
first_enqueued_attimestamptz—YESSet at the first successful queue send. A job counts as started only from this moment, or once the worker reports, which is how a start failure is told apart from a slow start.

Indexes

  • translation_jobs_pkey — UNIQUE on id
  • translation_jobs_job_id_key — UNIQUE on job_id
  • idx_translation_jobs_state — on state
  • idx_translation_jobs_submitted_at — on submitted_at DESC
  • idx_translation_jobs_task_id — on task_id WHERE task_id IS NOT NULL
  • idx_translation_jobs_quote_id — on quote_id WHERE quote_id IS NOT NULL (new)
Why first_enqueued_at matters: a paid job that never reached the queue must be refunded, and a slow job must not be. The LPO writes the job row first, then sends one queue message per language, and stamps first_enqueued_at on the first send that succeeds. A job with no stamp and no worker report never started, and its quote enters the start-failure refund; a job with the stamp is simply in progress.

2. translation_job_events

Purpose: The job audit log. Each pair start, success, failure and rejection is a separate row, which is what lets the status endpoint rebuild per-pair progress from Aurora long after the live Valkey state has expired.

8 columns

ColumnData TypeDefaultNullableDescription
id PKbigintauto-incrementNOEvent identifier
job_idvarchar(64)—NOJob this event belongs to (translation_jobs.job_id)
event_typevarchar(30)—NOEvent type, e.g. lang_started, lang_succeeded, lang_failed, lang_rejected
docvarchar(200)—YESDocument name, for pair-level events
langvarchar(12)—YESTarget language code. Widened from 5 to 12 characters so regional and script codes such as zh-TW and fa-AF fit.
detailjsonb{}YESEvent detail. New values: lang_rejected {"reason":"target_is_source"} (the page is already in the target language, never retried); lang_failed {"error":"enqueue-failed"} (written by the LPO for languages that were never sent); lang_failed {"error":"cancel-state-unknown"} (the worker could not confirm the job was still live before publishing, so it refused to publish). lang_started now also records source_provenance and lang_runtime_source.
created_attimestamptznow()NOEvent time
metricsjsonb—YESPer-pair metrics reported by the worker

Indexes

  • translation_job_events_pkey — UNIQUE on id
  • idx_translation_job_events_job_id — on job_id
  • idx_translation_job_events_created_at — on created_at DESC

3. translation_quotes

Purpose: Customer quotes and their Stripe payment. A quote prices up to 42 documents into up to 12 languages, holds that price for 72 hours, and remembers enough (fingerprints, per-pair prices, source languages) to re-check every document at acceptance and to refund any pair to the cent.

61 columns

The 61 columns read best in three groups: what was quoted, how the quote moved through its life, and how its money came back when something was not delivered. Rows with a green edge arrived with this release (migration 2026-10-09-03).

3.1 Quote, documents and price

ColumnData TypeDefaultNullableDescription
id PKbigintauto-incrementNOInternal identifier
quote_idvarchar(64)—NOPublic quote identifier: qt- plus the first 12 characters of a UUID (e.g., qt-a1b2c3d4-e5f). Unique.
api_key_idvarchar(128)—NOAPI key that requested the quote. Dashboard reads now match every translation key of the same user.
doc_urltext—NOURL of the first document (see doc_urls for all of them)
doc_namevarchar(255)—NOName of the first document
doc_size_bytesinteger—NOSize of the document in bytes. Nothing over 300 KB (307,200 bytes) is ever quoted.
estimated_chunksinteger—NOEstimated translation chunks
difficultyvarchar(21)standardNODifficulty: standard, technical or complex
code_blocksinteger0NOCode blocks detected
diagramsinteger0NOMermaid diagrams detected
langsjsonb—NOTarget languages, canonical codes after alias conversion and de-duplication (up to 12)
lang_countinteger—NONumber of target languages
cost_per_chunknumeric(8,4)—NOInternal: Bedrock cost per chunk. Never shown to the customer.
cost_per_pairnumeric(8,4)—NOInternal: blended price per pair. Never shown to the customer.
infra_per_pairnumeric(8,4)—NOInternal: infrastructure cost per pair
subtotalnumeric(10,4)—NOInternal: subtotal before markup
markup_pctinteger—NOMarkup percentage applied
total_pricenumeric(10,4)—NOThe price the customer pays (USD)
modelvarchar(50)claude-sonnet-4.6YESThe agent the customer chose, or per-language when the quote was auto-routed (the map is in model_by_lang). The column default is legacy; the quote handler always writes this column.
execution_modevarchar(20)expressNODelivery mode, express for every customer quote today
protected_termsjsonb[]YESThe customer's brand terms, protected during translation
created_attimestamptznow()NOQuote creation time
updated_attimestamptznow()NOLast change

3.2 Lifecycle, documents, source language and requote

ColumnData TypeDefaultNullableDescription
statevarchar(21)pendingNOLifecycle: pending, accepted, expired, superseded, refunded, partially_refunded. There is no CHECK on this column.
expires_attimestamptz—NOQuote expiry, 72 hours after creation (a requote gets its own 72 hours)
accepted_attimestamptz—YESWhen the customer accepted and paid
declined_attimestamptz—YESLegacy decline time
stripe_payment_intent_idvarchar(128)—YESStripe PaymentIntent for this quote
stripe_charge_idvarchar(128)—YESStripe Charge after payment
job_idvarchar(64)—YESThe parent translation job created at acceptance
doc_urlsjsonb—YESEvery document URL in the quote, trimmed and de-duplicated (up to 42)
doc_countinteger1NONumber of documents
total_pairsinteger0NODocuments × languages
doc_namesjsonb—YES{"<url>":"<name>"}: the delivered file name of each document
source_langsjsonb—YES{"<name>":{"lang":"<code>|auto","provenance":"stated|declared|detected|auto"}}: each document's source language and how we know it
doc_fingerprintsjsonb—YES{"<name>":{"url","alg":"tbfp1","content_sha256","raw_size","translatable_size"}}: the content fingerprint compared when the quote is accepted
pair_pricesjsonb—YES{"<name>":{"<lang>":3.0}}: the price of every pair, so any refund is exact
model_by_langjsonb—YES{"<lang>":"<model>"} when auto-routed; {} for an explicit agent
superseded_byvarchar(64)—YESThe newer quote that replaced this one (a requote, or a dashboard re-quote with supersedes_quote_id)
requoted_fromvarchar(64)—YESThe older quote this one was created to replace
accept_claimed_untiltimestamptz—YESThe accept claim. A second accept of the same quote inside this window is answered at once with tbts_quote_accept_in_progress, so one quote can never be charged twice.
How a stale quote is caught: at acceptance every document is fetched again and fingerprinted (tbfp1, a SHA-256 of the translatable content). Same content and same price: the job proceeds. Changed content at the same price: it proceeds with a notice. A new price or a rule change: the old quote is marked superseded, a new one is made (requoted_from points back), and accept answers 409 tbts_quote_requoted. A page that grew past 300 KB is refused with 400 tbts_doc_too_large and no new quote.

3.3 Refunds, cancellation and the free retry

ColumnData TypeDefaultNullableDescription
refunded_attimestamp—YESWhen the last refund was issued
refund_amountnumeric(10,2)NULLYESAmount of the last refund (USD)
refund_idvarchar(255)NULLYESStripe Refund ID of the last refund
refunded_totalnumeric(10,2)0NOEverything refunded on this quote so far, from every kind of refund (cancel, admin, failed pairs). Backfilled from refund_amount for existing refunded quotes.
cancelled_attimestamptz—YESWhen the customer cancelled
cancelled_bytext—YESWho cancelled
refund_duenumeric(10,2)—YESCancel refund awaiting approval
refund_statustext—YESCancel refund state (the approval flow)
failed_refund_statustext—YESThe failed-pair refund machine: window_open, retrying, due, issuing, issued, none, error (CHECK tq_failed_refund_status_check)
failed_refund_triggertext—YESstart_failed (the paid job never started) or job_terminal (the job finished with failed pairs)
failed_refund_window_ends_attimestamptz—YESEnd of the 72-hour window in which the customer can use the free retry
failed_refund_duenumeric(10,2)—YESAmount due for the undelivered pairs
failed_refund_amountnumeric(10,2)—YESAmount actually refunded
failed_refund_pairsjsonb—YESThe refunded document-language pairs
failed_refund_idtext—YESStripe Refund ID (idempotency key txfr-{quote_id}, so it can never be sent twice)
failed_refund_attimestamptz—YESWhen the failed-pair refund was issued
failed_refund_attemptsinteger0NOStripe attempts so far (the limit is refund.failed_pair_max_attempts)
failed_refund_last_errortext—YESLast Stripe error, for the operator
retry_job_idtext—YESThe job of the one free retry
retry_countinteger0NOFree retries used (at most one)

Indexes

  • translation_quotes_pkey — UNIQUE on id
  • translation_quotes_quote_id_key — UNIQUE on quote_id
  • idx_quotes_api_key — on api_key_id
  • idx_quotes_expires — on expires_at WHERE state = 'pending'
  • idx_quotes_state — on state
  • idx_quotes_failed_refund_active — on failed_refund_status WHERE it is window_open, retrying, due or issuing (new: the 15-minute refund sweeper reads only live rows)
One quote, one refund ledger. Cancel refunds, admin refunds and failed-pair refunds all add to refunded_total, and every refund is clamped to what is left, so a pair can never be refunded twice. The automatic failed-pair refund (failed_refund_*) runs behind refund.failed_pair_enabled, switched on 2026-10-11; the free retry (retry_job_id, retry_count) and the start-failure refund work from deploy.

4. translation_parameters

Purpose: Dedicated parameter store for the translation engine — separated from the general application_parameters table because translation is a standalone product with its own pricing, cost controls, and operational config. Cached in Valkey as the tx:params hash (27-hour TTL, so it always outlives the nightly refresh). Every parameter that governs translation behavior — per-token Bedrock rates, cost caps, markup percentages, batch config, and token estimation factors — lives here. Every LPO container reads Valkey first, then Aurora, then a hard-coded floor that is never zero, so a parameter change needs no code deploy: run POST /admin/translate/params/reload or let the nightly sync carry it.
Bedrock rates refresh themselves every night. The nightly sync job (BeastReconciler) reads each model's token rates from the public AWS Price List (pricing:GetProducts, priced for us-east-2), checks that every value is plausible, writes any change to the bedrock_pricing rows here, then copies the table into tx:params and confirms both stores agree. A failed fetch, a missing value or a jump of more than 3× in one night keeps that model's stored rates and raises one ops alert, so a bad night can never reprice a quote. Aurora stays the source of truth: Valkey only ever receives what Aurora holds. Keys follow bedrock.<rate key>.realtime.input_per_1m, with rate keys qwen3235b, deepseekv3, mistrallarge, haiku55, sonnet46, opus48 and opus5 (stored so a later switch needs no new data).

6 columns · 46 rows captured live on 2026-10-10, plus 6 refund rows from this release

ColumnData TypeDefaultNullableDescription
key PKvarchar—NOParameter key in dot-notation (e.g., bedrock.sonnet46.realtime.input_per_1m, refund.failed_pair_enabled)
valuetext—NOParameter value (numeric stored as text for flexibility)
descriptiontext''NOHuman-readable explanation of what this parameter controls
categoryvarchargeneralNOGrouping category: bedrock_pricing, token_estimation, cost_controls, customer_pricing, batch_config, refund
updated_attimestamptznow()NOLast modification timestamp
updated_byvarcharsystemNOWho last changed this parameter (admin email, sync-job, kiro)

Categories

CategoryRowsWhat It Controls
bedrock_pricing~30Per-token rates for each model × mode (realtime input/output, batch input/output, cache read/write). Drives all cost calculations.
token_estimation~12Tokens-per-byte ratio, output/input multiplier, cache hit rate, speed factors per model. Used to estimate job cost before submission.
cost_controls~9Daily spend cap ($600) and the daily token limit, both checked before a customer is charged. controls.max_docs_per_request is now '42', a mirror of the code constant and not read for enforcement: the real limits (12 languages, 42 documents, 300 KB, 9 quotes per batch) are constants in internal/txlimits.
customer_pricing~9Markup percentage (30%), infra cost per pair, tier discount factors, quote validity (72 hours).
batch_config~6S3 bucket for batch inference, IAM role ARN, polling interval (33s), JSONL processing config.
refund6The failed-pair refund machine: refund.failed_pair_enabled (on since 2026-10-11; code default 'false'), refund.failed_pair_window_hours (72), refund.failed_pair_max_attempts (3), refund.sweep_interval_minutes (15, a multiple of 3 clamped to 3–60), refund.failed_pair_since (set in the same statement that turns the flag on) and refund.start_failure_since (stamped by migration 03b at deploy).
Admin access: GET /admin/translate/params (list all), POST /admin/translate/params (upsert), POST /admin/translate/params/reload (force cache refresh). Dashboard: GET/POST/DELETE /dashboard/api/translate/params.

5. bedrock_model_catalog

Purpose: Registry of all Bedrock models available to the translation engine. The agent-agnostic architecture reads this catalog to resolve friendly model names to Bedrock model IDs, determine regional availability, and select inference types (realtime vs batch). Enables adding new models (or blocking broken ones) without code changes.

Corrected 2026-08-12 — no lookupModelID() function exists. This entry previously claimed that function consulted the catalog to resolve models and enforce blocked regions. It doesn't exist anywhere in the codebase, and nothing reads this table's blocked=true rows — they document intent, not a control. Region blocking (specifically, the hard rule that no Canadian region is ever used) is actually enforced by FAILOVER_REGIONS in tbi-translate-worker/translator/engine.py being a fixed allow-list that simply never contains a Canadian region, backed by an import-time assertion that fails fast if one is ever added. See Trinity-Beast-TBI-Translation-Engine.html §12.1 for the real mechanism. Model-ID resolution for an active job reads directly from this table's live rows via ordinary SQL — there is no dedicated named function performing that lookup.

12 columns · 20 rows

ColumnData TypeDefaultNullableDescription
id PKintegerauto-incrementNOAuto-incrementing identifier
friendly_namevarchar—NOHuman-friendly model name used in API requests (e.g., claude-sonnet-4.6, qwen3-235b)
display_namevarchar—NOMarketing display name (e.g., "Claude Sonnet 4.6", "Qwen3 235B")
bedrock_model_idvarchar—NOFull Bedrock model ARN/ID (e.g., us.anthropic.claude-sonnet-4-6)
regionvarchar—NOAWS region where this model is invoked. HARD RULE: ca-central-1 and ca-west-1 are NEVER used.
inference_typevarchar—NOInvocation method: realtime (InvokeModel) or batch (CreateModelInvocationJob)
priorityinteger1NOPreference order when multiple entries exist for the same friendly_name (lower = preferred). Used for regional failover.
enabledbooleantrueNOWhether this catalog entry is active. Disabled entries are skipped during model resolution.
notestext''NOAdmin notes (why it's blocked, performance observations, etc.)
verified_attimestamptznow()NOWhen this model was last verified to be responding correctly in its region
created_attimestamptznow()NOWhen this catalog entry was created
blockedbooleanfalseNOHard block — entries with blocked=true are documentation of regions/models that must NEVER be used (CA regions). Unlike enabled=false (temporarily off), blocked entries represent permanent policy constraints.

Format Families

The translation engine routes models through one of three format families based on their prefix. Each family has its own request/response JSON structure — the engine handles this transparently via DetectFamily(), BuildRequestBody(), and ParseResponseText() in internal/bedrock/formats.go:

FamilyPrefix MatchModels
anthropicanthropic.*, us.anthropic.*Claude Haiku 5.5, Claude Sonnet 4.6, Claude Opus 4.8
openaiqwen.*, deepseek.*, mistral.*Qwen3 235B, DeepSeek V3, Mistral Large
novaamazon.nova.*(Reserved — Nova Pro removed from active roster due to HTML tag dropping)
Blocked regions (permanent policy): ca-central-1 and ca-west-1 have blocked=true entries in this catalog as a record of the policy. The enforcement is the worker's fixed FAILOVER_REGIONS allow-list, which never contains a Canadian region and is backed by an import-time assertion (see the correction above). This is a hard architectural constraint, not a temporary disable.

6. translation_tasks

Purpose: Task Organizer — parent-child orchestration for translation jobs. A Task is the unit above a Job: 1 customer acceptance = 1 Task = N Jobs. One notification per Task (not per Job) when all Jobs reach terminal state. Tracks task lifecycle, customer email for notification routing, and quote linkage for the payment flow. A customer polls a batch with GET /translate/task/{task_id}.

16 columns

ColumnData TypeDefaultNullableDescription
task_id PKvarchar(48)—NOPublic task identifier
task_typevarchar(24)admin_batchNOacceptance (a customer's batch acceptance) or admin_batch (internal)
statevarchar(24)queuedNOTask state: queued, running, succeeded, partial, failed, cancelled
customer_emailvarchar(255)—YESWhere the one task-level completion email goes (acceptance tasks)
quote_idsjsonb[]NOQuotes bundled into this task (up to 9)
job_idsjsonb[]NOChild jobs of this task
total_jobsinteger0NOChild jobs submitted
completed_jobsinteger0NOJobs that succeeded
failed_jobsinteger0NOJobs that failed
cancelled_jobsinteger0NOJobs that were cancelled
notification_sentbooleanfalseNOPrevents a second completion email
submitted_attimestamptznow()NOWhen the task was created
completed_attimestamptz—YESWhen every child job reached a terminal state
created_attimestamptznow()NORow creation time
updated_attimestamptznow()NOLast change
recorded_job_idstext[]ARRAY[]YESJobs already counted, so a repeated completion never counts twice

Indexes

  • translation_tasks_pkey — UNIQUE on task_id

Aurora Functions

  • create_translation_task(task_id, task_type, customer_email, quote_ids, job_ids, total_jobs) — Creates the task record
  • get_task_status(task_id) — Returns task + all jobs in one call (JOIN)
  • get_active_tasks() — Returns all non-terminal tasks (poll loop query)
  • record_task_job_completed(task_id, job_id, job_state) — Atomic counter update + "all done?" boolean
  • mark_task_notified(task_id) — Idempotent notification flag set
  • cancel_task_remaining(task_id, reason) — Cancel all pending jobs, close task
Relationship: translation_jobs.task_id is a nullable link column (with a partial index on non-NULL values) from each child job to its parent task; it is not a declared foreign key. Jobs created outside the Task Organizer (direct POST /admin/translate) have task_id = NULL.

7. translation_language_profiles

Purpose: Per-language tuning: chunk size, tag limits, retries, temperature and the auto-tuned density knobs. The 11 hand-tuned profiles of our own library are untouched; the release seeds 116 more by copying each new language's tuning_lang row, so every one of the 127 languages starts from proven settings instead of guesses.

18 columns · 127 rows

ColumnData TypeDefaultNullableDescription
lang_code PKvarchar(12)—NOLanguage code. Widened from 5 to 12 characters for codes such as zh-TW.
display_namevarchar(50)—NOLanguage name
script_familyvarchar(20)—NOScript family (latin, cjk, indic, arabic, cyrillic, ...). Drives preprocessor density and chunk sizing.
max_chunk_kbinteger15NOMaximum chunk size in KB for this language
max_code_tagsinteger81NOMaximum code tags per chunk before a forced split (a multiple of 3)
token_expansion_factornumeric(3,2)1.00NOExpected output/input token ratio
max_retriesinteger1NORetry attempts per chunk on validation failure
retry_chunk_shrink_pctinteger30NOHow much smaller a retried chunk is (30 = 70% of the original)
model_overridevarchar(100)NULLYESEngine-level model override for this language
temperaturenumeric(2,1)0.3NOBedrock temperature for this language
max_output_tokensinteger4096NOOutput token ceiling per Bedrock call
priorityinteger6NOProcessing priority (lower runs first). The 116 seeded rows use 12.
enabledbooleantrueNOWhether this profile is active
notestext—YESOperational notes. Seeded rows say which tuning row they were copied from.
updated_attimestamptznow()NOLast change
updated_byvarchar(100)systemNOWho last changed the row
density_lift_thresholdnumeric(4,3)NULLYESAuto-tuned. Density ratio above which a container is lifted whole. Tightened by telemetry when the tag drop rate passes 3%. Floor 0.015.
density_max_proseinteger—YESAuto-tuned. Most prose characters a container may hold and still be lifted

Indexes

  • translation_language_profiles_pkey — UNIQUE on lang_code
Auto-tuning: the worker's _auto_tune_density_threshold() reads the last 7 days of translation_chunk_telemetry (code tags in versus out) and tightens the density threshold for a language that keeps dropping tags: 3–6% drop rate → -0.005, 6–12% → -0.01, above 12% → -0.015, never below 0.015. It runs once per container lifetime per language.
Aurora functions: get_language_profile(p_lang) returns one profile row and is kept unchanged for compatibility. The worker now reads get_language_runtime(p_lang) (section 8), which joins the profile to its catalog row.

8. translation_supported_languages

Purpose: The language catalog: the single list of the 127 languages a customer can order. Every quote, the admin submit path and the public GET /translate/languages resolve codes against it, which is why an unsupported code can never be quoted, charged and silently mistranslated. The rows are generated from one file, migrations/data/translation_language_catalog.tsv: the 75 Amazon Translate languages together with the 119 of Qwen 3.

17 columns · 127 rows

ColumnData TypeDefaultNullableDescription
lang_code PKvarchar(10)—NOCanonical code, e.g. es, zh-TW, fa-AF
english_namevarchar(120)—NOEnglish name (e.g., Persian, Tagalog (Filipino))
sourcevarchar(40)aws_translateNOWhere the row first came from. A re-run of the catalog migration never changes it.
statusvarchar(20)supportedNOsupported, blocked or unverified (CHECK). An admin's choice here always survives a re-run.
notestext—YESAdmin notes
created_attimestamptznow()NORow creation time
updated_attimestamptznow()NOLast change
updated_byvarchar(120)systemNOWho last changed the row
native_namevarchar(96)—YESThe language's own name for itself (Español, 日本語), shown in the dashboard picker
scriptvarchar(4)—YESISO 15924 script code (Latn, Arab, Hans, ...). CHECK tsl_script_present requires both script and native name.
rtlbooleanfalseNOWritten right to left. True for 15 languages; their delivered files are marked dir="rtl".
word_spacedbooleantrueNOFalse for the 8 languages written without spaces (ja, zh, zh-TW, yue, th, lo, km, my), so the term-spacing check skips them
base_langvarchar(10)—YESThe parent language of a regional form (es-MX → es). Foreign key tsl_base_fk to this table.
tuning_langvarchar(10)—YESWhose chunk limits and prompts this language borrows (fa → Urdu, ko → Japanese)
provenancevarchar(48)manualNOWhy the row exists: aws_translate, qwen3 or both
target_allowedbooleantrueNOWhether the language can be ordered as a target (true for all 127)
default_modelvarchar(32)—YESThe auto-routing agent for this language. claude-sonnet-4.6 for am, ha, mn, ps and so; empty for the rest, which run on Qwen 3 235B. An admin's value survives a re-run.

Indexes

  • translation_supported_languages_pkey — UNIQUE on lang_code
  • idx_translation_supported_languages_status — on status
Aurora function get_language_runtime(p_lang) (new) returns 24 columns: the catalog row LEFT JOINed to its profile, matched case-insensitively. The worker calls it once per language and caches the answer for 15 minutes, falling back to a generated snapshot (translator/language_catalog_snapshot.json) if Aurora is unreachable, so a language never fails because a lookup did.
Aliases have no table, on purpose. The 36 alternate codes (nb → no, zh-Hant → zh-TW, iw → he, any ar-XX → Modern Standard Arabic ar) live in migrations/data/translation_language_aliases.tsv, are generated into the LPO (internal/txlangs/aliases_gen.go) and the worker snapshot, and are published in the aliases field of GET /translate/languages. They are converted quietly, before any limit is counted. A region tag that is neither a catalog code nor an alias, such as en-US or es-AR, is not in the file: the resolver reduces it to its base language separately. Arabic dialects keep their own codes (arz, apc, ...).

9. translation_chunk_telemetry

Purpose: One row per translated chunk attempt: size, tokens, sentinels, code tags and outcome. It is the evidence the auto-tuner learns from, and the first place to look when one language keeps failing on one document.

23 columns

ColumnData TypeDefaultNullableDescription
id PKbigintauto-incrementNORow identifier
job_idvarchar(50)—NOJob the chunk belongs to
docvarchar(200)—NODocument name
langvarchar(12)—NOTarget language. Widened from 5 to 12 characters.
chunk_indexinteger—NOPosition of the chunk in the document
attemptinteger1NOAttempt number for this chunk
chunk_size_bytesinteger—NOChunk size in bytes
input_tokensinteger—YESBedrock input tokens
output_tokensinteger—YESBedrock output tokens
expansion_rationumeric(4,2)—YESOutput/input token ratio actually observed
sentinel_countinteger—YESSentinels sent with the chunk
sentinels_restoredinteger—YESSentinels found and restored in the answer
sentinel_integrityboolean—YESWhether every sentinel came back intact
code_tags_ininteger—YESCode tags in the source chunk
code_tags_outinteger—YESCode tags in the translated chunk (the auto-tuner compares the two)
validation_passedboolean—YESWhether the chunk passed validation
validation_errorsjsonb—YESValidation failures, if any
duration_msinteger—YESTime spent on the chunk
model_usedvarchar(100)—YESBedrock model ID that answered
statusvarchar(20)—NOChunk outcome
error_classvarchar(50)—YESError category
error_detailtext—YESError text
created_attimestamptznow()NORow creation time

Indexes

  • translation_chunk_telemetry_pkey — UNIQUE on id
  • idx_chunk_telemetry_job — on job_id
  • idx_chunk_telemetry_doc_lang — on doc, lang
  • idx_chunk_telemetry_lang — on lang, status

Entity Relationships

Two pictures tell the whole schema. The first follows the money and the work: a quote becomes a job, a job writes events and telemetry, and a batch groups quotes under one task. The second is the configuration every job reads: which languages exist, how each one is tuned, what each model costs.

Diagram 1.1 — Quotes, Jobs and Tasks
erDiagram
    translation_tasks ||--o{ translation_jobs : "task_id (1 task = N jobs)"
    translation_quotes ||--o{ translation_jobs : "quote_id (parent job + free retry)"
    translation_quotes ||--o| translation_quotes : "superseded_by / requoted_from"
    translation_jobs ||--o{ translation_job_events : "job_id (audit trail)"
    translation_jobs ||--o{ translation_chunk_telemetry : "job_id (per-chunk metrics)"
    translation_quotes {
        varchar quote_id UK
        varchar job_id
        varchar retry_job_id
        varchar superseded_by
        text failed_refund_status
        numeric refunded_total
    }
    translation_jobs {
        varchar job_id UK
        varchar quote_id
        varchar task_id
        varchar retry_of
        timestamptz first_enqueued_at
    }
    translation_tasks {
        varchar task_id PK
        jsonb quote_ids
    }
        
Diagram 1.2 — Languages, Profiles and Parameters
erDiagram
    translation_supported_languages ||--o| translation_language_profiles : "lang_code"
    translation_supported_languages |o--o{ translation_supported_languages : "base_lang (regional form)"
    translation_supported_languages ||--o{ translation_jobs : "every language resolved here"
    translation_language_profiles ||--o{ translation_jobs : "per-language tuning"
    bedrock_model_catalog ||--o{ translation_jobs : "model selection"
    translation_parameters ||--o{ translation_jobs : "rates, caps, refund rules"
    translation_supported_languages {
        varchar lang_code PK
        bool rtl
        bool word_spaced
        varchar base_lang FK
        varchar tuning_lang
        varchar default_model
    }
    translation_language_profiles {
        varchar lang_code PK
        int max_chunk_kb
        numeric density_lift_threshold
    }
        

Key Relationships

  • translation_quotes.job_id → translation_jobs.job_id (the parent job, set at acceptance)
  • translation_jobs.quote_id → translation_quotes.quote_id (new: set on the parent job and on its free retry, so both directions are one lookup)
  • translation_quotes.retry_job_id → translation_jobs.job_id (new: the one free retry)
  • translation_quotes.superseded_by / requoted_from → translation_quotes.quote_id (new: a requote and the quote it replaced)
  • translation_jobs.task_id → translation_tasks.task_id (link column, partial index on non-NULL)
  • translation_job_events.job_id and translation_chunk_telemetry.job_id → translation_jobs.job_id
  • translation_supported_languages.lang_code → translation_language_profiles.lang_code, and base_lang → lang_code of the same table (foreign key tsl_base_fk)

Valkey Cache Keys

Purpose: Aurora is the permanent ledger and Valkey is the fast read. Live jobs are read from Valkey first and completed jobs fall back to Aurora, and every key here can be lost without losing anything: the system keeps working on Aurora alone.
Key PatternTypeTTLContent
tx:job:{id}HashNone while live; 6 days once the job endsLive job state (status, progress, per-pair results). The customer status endpoints read it first and fall back to Aurora.
tx:activeSetManagedCurrently running job IDs (at 12 or more the LPO logs a warning and still queues; nothing caps concurrency)
tx:historyListNone (capped)Completed job summaries, newest first
tx:idempotency:{key}String24hIdempotency deduplication
tx:paramsHash27 htranslation_parameters cache, refreshed nightly by the sync job (Bedrock rates included) and on reload
tx:supported_langsHash27 hLanguage code → status, the compact form of the catalog
tx:lang_catalogString (JSON)27 hThe full 127-row catalog. Every LPO container also refreshes its copy in place every 15 minutes, so a language change reaches every container without a restart.
tx:chunk-hash:*StringPermanentPer-chunk content hashes (delta detection)
dashboard:notifications:seen:user:{users.id}String—Dashboard notification badge, now per user across every translation key (one fallback read of the old per-key value)
autoops:bedrock:spend:dailyString24hToday's Bedrock translation spend ($)
autoops:bedrock:tokens:input:dailyString24hToday's input token count
autoops:bedrock:tokens:output:dailyString24hToday's output token count

Admin API Endpoints

Purpose: Admin endpoints for managing translation data. All require X-Admin-Key header.
EndpointMethodPurpose
/admin/translatePOSTSubmit a translation job (up to 42 documents and 12 languages, or "all" for the internal 11)
/admin/translate/status/{job_id}GETReal-time per-pair progress
/admin/translate/queueGETActive queue with all running/queued jobs
/admin/translate/healthGETSystem health (spend, active jobs)
/admin/translate/historyGETJob history (last 50)
/admin/translate/cancel/{job_id}POSTCancel a running job
/admin/translate/retry-failed/{job_id}POSTRetry only the failed pairs of a partial job, on the same model as the original job. On a customer job it uses the quote's one free retry.
/admin/translate/paramsGET/POSTList all / upsert translation parameters
/admin/translate/params/reloadPOSTRefresh the Valkey cache from Aurora
/admin/translate/languagesGET/POSTList the catalog / update one language (a new code needs its English name, native name, script and tuning language)
/admin/translate/languages/reloadPOSTRefresh the catalog in place
/admin/translate/refund/{quote_id}POSTFull or partial refund, allowed on accepted or partially_refunded quotes and clamped to what is left
/admin/translate/refund-approve/{quote_id}POSTApprove a customer's cancel refund
/admin/translate/refund-sweepPOSTRun one pass of the 15-minute failed-pair refund sweeper now
Agents and languages for everyone: the agent list is the public GET /translate/models (there is no admin models route), and the live catalog with its limits and aliases is the public GET /translate/languages. Dashboard equivalents: GET/POST/DELETE /dashboard/api/translate/params, POST /dashboard/api/translate/params/reload — same functionality, different auth path (magic link session vs admin key).

Schema Summary

9 tables, 197 columns in total, plus the Task Organizer functions and two language functions (get_language_profile, get_language_runtime). The columns of eight tables were read from the live schema on 2026-10-10 and include the release migrations; bedrock_model_catalog was not part of that capture and keeps its earlier column list. Row counts change daily, so read them live rather than from a page.

TableColumnsPurpose
translation_jobs36Job orchestration and state
translation_job_events8Granular audit trail
translation_quotes61Customer quotes, Stripe payment, requotes and refunds
translation_parameters6Operational configuration store
bedrock_model_catalog12Multi-provider model registry
translation_tasks16Parent-child task orchestration
translation_language_profiles18Per-language tuning + auto-tuning
translation_supported_languages17The 127-language catalog
translation_chunk_telemetry23Per-chunk metrics
Related documents: