M3: cors_origins setting in config.py (env CORS_ORIGINS); main.py reads from settings.
M4: add build_order_line_step_render_dir() to render_paths.py; tasks.py drops placeholder.mp4 trick.
M5: unknown workflow graph nodes now fail the run (status="failed" + logger.error) instead of silently skipping.
M6: invoice line description is now "{product} — {output_type}" instead of bare UUID; eager-loads relations.
M7: order_number_prefix setting in config.py (env ORDER_NUMBER_PREFIX, default "SA").
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
H2: list_invoices now passes tenant_id (from current_user) to get_invoices;
get_invoices applies WHERE tenant_id filter for non-global-admin users;
get_invoice_endpoint returns 404 when tenant mismatch for non-admins.
H3: InvoiceStatusUpdate.status changed to Literal["draft","sent","paid","cancelled"]
for schema-level validation; guard also added in update_invoice_status service.
H5: _settings_to_out masks smtp_password as "***" when set, "" when empty;
update_settings skips writing when value is the "***" sentinel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migration 035: tenants table with 'Schaeffler' default seed.
Migration 036: tenant_id FK on all tables, RLS policies, backfill.
New domains/tenants/ with CRUD router (admin only).
All domain models extended with tenant_id FK.
core/database.py: get_db_for_tenant with RLS context setter.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move all models/schemas/services/routers into app/domains/.
Keep backward-compat shims in old locations for imports.
Preserves domains/rendering/tasks.py from Phase A.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>