# Background worker ownership and activation

Updated: 2026-08-02

## Tenant execution contract

HTTP requests derive `JobTrackerContext.CurrentUserId` from the authenticated request. Hosted services have no HTTP context, so deny-on-null query filters intentionally return no tenant rows.

`BackgroundTenantRunner` is the only worker bypass for the four job-owner schedulers. It uses `IgnoreQueryFilters` only to enumerate distinct non-empty job owners, then creates a fresh scope per owner and sets `CurrentUserService` before resolving the scoped `JobTrackerContext`. All work queries run through the normal tenant filters. An owner failure is counted and isolated; logs contain worker name, exception type and aggregate counts, not owner IDs or private content. An HTTP context cannot be replaced by a background owner.

This is a sequential, single-instance foundation. Generic operation leasing now exists in OPS-001A, but notifications, bounded AI handlers and multi-replica scheduling belong to OPS-001B/C and AI-001 and must precede activation that needs them.

## Hosted-service inventory

| Service | Tenant behavior | Side effect | Activation |
|---|---|---|---|
| `RulesHostedService` | owner runner + normal filters/per-user rules | changes job status | `Workers:RulesEnabled=false` by default; keep off until user-visible notification/audit behavior is ready |
| `FollowUpReminderHostedService` | owner runner + normal filters | sends email, then marks date | both `Workers:FollowUpRemindersEnabled` and `Email:FollowUpReminders:Enabled`; keep off until persistent notification/idempotency work |
| `DailyExportHostedService` | owner runner + normal filters; one hashed-owner atomic file | writes local JSON | both `Workers:DailyExportEnabled` and `Exports:DailyEnabled`; keep off pending retention/operator rollout |
| `JobEnrichmentHostedService` | owner runner + normal filters | deterministic tags and AI summary | `Workers:JobEnrichmentEnabled=false`; do not enable before Pro/privacy/provider/queue gates |
| `CvProcessingHostedService` | existing explicit run owner on every unfiltered query | user-requested CV parsing/AI | unchanged; persistent run rows recover at startup, process-local wake-up remains single-instance |
| `SummarizerProbeHostedService` | tenant-neutral; no user payload | AI-sidecar health probe | existing probe settings; unchanged |
| `DatabaseBackupHostedService` | tenant-neutral complete database snapshot | local backup | existing backup settings; unchanged |

## Rollout and rollback

Changing old settings alone cannot activate the four repaired workers; the new worker-specific switch must also be true. Enable one worker at a time only after its listed dependencies, fake/synthetic tests, operator monitoring and rollback are ready. Rollback is setting its worker switch to false; do not delete outputs or undo already-applied user-visible changes without a separate reviewed procedure.
