- Add `organization_id` field (denormalized from project.client_id) to Job,
ReviewNote, VttVersion, and AuditLog models
- Introduce `get_user_org_ids()` and `assert_job_in_user_org()` helpers in
`core/dependencies.py` — all staff roles now scope to their orgs; the
dangerous `None` (unrestricted) fallback for LINGUIST/REVIEWER/PRODUCTION
with no team assignment is eliminated (returns `[]` instead)
- Apply `assert_job_in_user_org` to `GET /jobs/{id}`, review-notes, and
vtt-versions endpoints; bulk delete/approve/return-to-qc now skip jobs
outside the requester's org instead of mutating cross-tenant data
- WebSocket `/ws/jobs/{job_id}` subscribe checks org membership before
accepting the connection
- `POST /jobs` accepts `client_id` form field; derives `organization_id`
from project lookup; removes blocking `time.sleep(1)` debug artifact
- `audit_logger.log_action` and `log_job_action` propagate `organization_id`
so audit entries are org-scoped
- Add migration script `migrations/2026_05_add_organization_id.py` to
backfill existing documents and create compound indexes
- Add `tests/unit/test_cross_tenant_isolation.py` with 10 unit tests
covering ADMIN bypass, same-org pass, cross-org 404, project fallback,
and legacy-job owner check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>