Full-stack Amazon AI Transcreation Platform with: - FastAPI backend (async, PostgreSQL, Redis, Celery) with 11 DB tables - JWT auth (SSO-ready abstract provider pattern) - 6-agent pipeline orchestrator with deterministic modules - Next.js 14 frontend with Amazon branding (Ember fonts, orange/dark theme) - Job wizard, monitoring HUD, output review, admin screens - 154 TM/reference files imported, 12 locales configured - Docker Compose for all services Agents 2-5 (TM retrieval, ranker, transcreator, compliance) are stubs pending Phase 3 LLM integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
219 lines
12 KiB
Python
219 lines
12 KiB
Python
"""initial_schema
|
|
|
|
Revision ID: d4a016fd0817
|
|
Revises:
|
|
Create Date: 2026-04-10 16:25:45.318282
|
|
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = 'd4a016fd0817'
|
|
down_revision: Union[str, None] = None
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# ### commands auto generated by Alembic - please adjust! ###
|
|
op.create_table('clients',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('name', sa.String(length=255), nullable=False),
|
|
sa.Column('settings', sa.JSON(), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('users',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('email', sa.String(length=255), nullable=False),
|
|
sa.Column('name', sa.String(length=255), nullable=False),
|
|
sa.Column('password_hash', sa.String(length=255), nullable=False),
|
|
sa.Column('role', sa.Enum('admin', 'tm_manager', 'reviewer', name='user_role', create_constraint=True), nullable=False),
|
|
sa.Column('status', sa.Enum('active', 'inactive', name='user_status', create_constraint=True), nullable=False),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.PrimaryKeyConstraint('id'),
|
|
sa.UniqueConstraint('email')
|
|
)
|
|
op.create_table('audit_logs',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('user_id', sa.Uuid(), nullable=True),
|
|
sa.Column('action', sa.String(length=100), nullable=False),
|
|
sa.Column('entity_type', sa.String(length=100), nullable=False),
|
|
sa.Column('entity_id', sa.String(length=255), nullable=False),
|
|
sa.Column('details', sa.JSON(), nullable=True),
|
|
sa.Column('timestamp', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('ip_address', sa.String(length=45), nullable=True),
|
|
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('jobs',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('client_id', sa.Uuid(), nullable=False),
|
|
sa.Column('created_by', sa.Uuid(), nullable=False),
|
|
sa.Column('job_ref', sa.String(length=100), nullable=True),
|
|
sa.Column('campaign_name', sa.String(length=255), nullable=False),
|
|
sa.Column('programme', sa.Enum('retail', 'prime', 'brand', name='programme_type', create_constraint=True), nullable=False),
|
|
sa.Column('channel', sa.String(length=100), nullable=False),
|
|
sa.Column('sub_channel', sa.String(length=100), nullable=True),
|
|
sa.Column('context_prompt', sa.Text(), nullable=True),
|
|
sa.Column('job_type', sa.Enum('main', 'derived', name='job_type', create_constraint=True), nullable=False),
|
|
sa.Column('parent_job_id', sa.Uuid(), nullable=True),
|
|
sa.Column('status', sa.Enum('created', 'validating', 'queued', 'running', 'partial_complete', 'complete', 'error', 'exported', name='job_status', create_constraint=True), nullable=False),
|
|
sa.Column('total_token_usage', sa.Integer(), nullable=False),
|
|
sa.Column('total_estimated_cost', sa.Float(), nullable=False),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'),
|
|
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
|
|
sa.ForeignKeyConstraint(['parent_job_id'], ['jobs.id'], ),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('reference_files',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('client_id', sa.Uuid(), nullable=False),
|
|
sa.Column('file_type', sa.Enum('glossary', 'blacklist', 'tov_global', 'tov_supplement', 'locale_considerations', 'date_pct_formats', name='reference_file_type', create_constraint=True), nullable=False),
|
|
sa.Column('locale_scope', sa.String(length=10), nullable=False),
|
|
sa.Column('filename', sa.String(length=255), nullable=False),
|
|
sa.Column('file_path', sa.String(length=500), nullable=False),
|
|
sa.Column('uploaded_by', sa.Uuid(), nullable=True),
|
|
sa.Column('uploaded_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('last_updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('version', sa.Integer(), nullable=False),
|
|
sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'),
|
|
sa.ForeignKeyConstraint(['uploaded_by'], ['users.id'], ),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('tm_file_registry',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('client_id', sa.Uuid(), nullable=False),
|
|
sa.Column('locale_code', sa.String(length=10), nullable=False),
|
|
sa.Column('channel', sa.String(length=100), nullable=False),
|
|
sa.Column('filename', sa.String(length=255), nullable=False),
|
|
sa.Column('file_path', sa.String(length=500), nullable=False),
|
|
sa.Column('segment_count', sa.Integer(), nullable=False),
|
|
sa.Column('uploaded_by', sa.Uuid(), nullable=True),
|
|
sa.Column('uploaded_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('last_updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('version', sa.Integer(), nullable=False),
|
|
sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'),
|
|
sa.ForeignKeyConstraint(['uploaded_by'], ['users.id'], ),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('user_clients',
|
|
sa.Column('user_id', sa.Uuid(), nullable=False),
|
|
sa.Column('client_id', sa.Uuid(), nullable=False),
|
|
sa.Column('role_override', sa.String(length=50), nullable=True),
|
|
sa.ForeignKeyConstraint(['client_id'], ['clients.id'], ondelete='CASCADE'),
|
|
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
|
|
sa.PrimaryKeyConstraint('user_id', 'client_id')
|
|
)
|
|
op.create_table('locale_instances',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('job_id', sa.Uuid(), nullable=False),
|
|
sa.Column('locale_code', sa.String(length=10), nullable=False),
|
|
sa.Column('locale_type', sa.Enum('main', 'derived', name='locale_type', create_constraint=True), nullable=False),
|
|
sa.Column('status', sa.Enum('queued', 'running', 'complete', 'error', name='locale_status', create_constraint=True), nullable=False),
|
|
sa.Column('started_at', sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column('token_usage', sa.Integer(), nullable=False),
|
|
sa.Column('estimated_cost', sa.Float(), nullable=False),
|
|
sa.Column('output_file_path', sa.String(length=500), nullable=True),
|
|
sa.Column('error_log', sa.Text(), nullable=True),
|
|
sa.Column('tm_files_loaded', sa.JSON(), nullable=True),
|
|
sa.Column('ref_files_loaded', sa.JSON(), nullable=True),
|
|
sa.Column('agent_version', sa.String(length=50), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.ForeignKeyConstraint(['job_id'], ['jobs.id'], ondelete='CASCADE'),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('source_lines',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('job_id', sa.Uuid(), nullable=False),
|
|
sa.Column('row_order', sa.Integer(), nullable=False),
|
|
sa.Column('en_gb', sa.Text(), nullable=False),
|
|
sa.Column('copy_type', sa.String(length=100), nullable=True),
|
|
sa.Column('creative_guidance', sa.Text(), nullable=True),
|
|
sa.Column('visual_ref', sa.String(length=500), nullable=True),
|
|
sa.Column('char_limit', sa.String(length=50), nullable=True),
|
|
sa.Column('is_display_format', sa.Boolean(), nullable=False),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.ForeignKeyConstraint(['job_id'], ['jobs.id'], ondelete='CASCADE'),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('output_rows',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('instance_id', sa.Uuid(), nullable=False),
|
|
sa.Column('line_id', sa.Uuid(), nullable=False),
|
|
sa.Column('row_order', sa.Integer(), nullable=False),
|
|
sa.Column('confidence_tier', sa.Enum('high', 'moderate', 'low', name='confidence_tier', create_constraint=True), nullable=False),
|
|
sa.Column('option_1', sa.Text(), nullable=False),
|
|
sa.Column('backtranslation_1', sa.Text(), nullable=False),
|
|
sa.Column('rationale_1', sa.Text(), nullable=False),
|
|
sa.Column('option_2', sa.Text(), nullable=True),
|
|
sa.Column('backtranslation_2', sa.Text(), nullable=True),
|
|
sa.Column('rationale_2', sa.Text(), nullable=True),
|
|
sa.Column('option_3', sa.Text(), nullable=True),
|
|
sa.Column('backtranslation_3', sa.Text(), nullable=True),
|
|
sa.Column('rationale_3', sa.Text(), nullable=True),
|
|
sa.Column('tm_entries_cited', sa.JSON(), nullable=True),
|
|
sa.Column('winning_seg_key', sa.String(length=255), nullable=True),
|
|
sa.Column('character_count_option_1', sa.Integer(), nullable=True),
|
|
sa.Column('character_count_option_2', sa.Integer(), nullable=True),
|
|
sa.Column('character_count_option_3', sa.Integer(), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.ForeignKeyConstraint(['instance_id'], ['locale_instances.id'], ondelete='CASCADE'),
|
|
sa.ForeignKeyConstraint(['line_id'], ['source_lines.id'], ondelete='CASCADE'),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('token_usage_logs',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('instance_id', sa.Uuid(), nullable=False),
|
|
sa.Column('agent_name', sa.String(length=100), nullable=False),
|
|
sa.Column('model', sa.String(length=100), nullable=False),
|
|
sa.Column('input_tokens', sa.Integer(), nullable=False),
|
|
sa.Column('output_tokens', sa.Integer(), nullable=False),
|
|
sa.Column('total_tokens', sa.Integer(), nullable=False),
|
|
sa.Column('estimated_cost_usd', sa.Float(), nullable=False),
|
|
sa.Column('timestamp', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.ForeignKeyConstraint(['instance_id'], ['locale_instances.id'], ondelete='CASCADE'),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_table('feedback',
|
|
sa.Column('id', sa.Uuid(), nullable=False),
|
|
sa.Column('output_id', sa.Uuid(), nullable=False),
|
|
sa.Column('user_id', sa.Uuid(), nullable=False),
|
|
sa.Column('option_column', sa.Integer(), nullable=False),
|
|
sa.Column('flag_type', sa.Enum('approved', 'needs_revision', 'comment', name='flag_type', create_constraint=True), nullable=False),
|
|
sa.Column('comment', sa.Text(), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.ForeignKeyConstraint(['output_id'], ['output_rows.id'], ondelete='CASCADE'),
|
|
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
# ### end Alembic commands ###
|
|
|
|
|
|
def downgrade() -> None:
|
|
# ### commands auto generated by Alembic - please adjust! ###
|
|
op.drop_table('feedback')
|
|
op.drop_table('token_usage_logs')
|
|
op.drop_table('output_rows')
|
|
op.drop_table('source_lines')
|
|
op.drop_table('locale_instances')
|
|
op.drop_table('user_clients')
|
|
op.drop_table('tm_file_registry')
|
|
op.drop_table('reference_files')
|
|
op.drop_table('jobs')
|
|
op.drop_table('audit_logs')
|
|
op.drop_table('users')
|
|
op.drop_table('clients')
|
|
# ### end Alembic commands ###
|