- Shipped
- November 13, 2026 at 2:17 AM UTC
- Author
- Kamo
- Commit
- 7f9bd03
Scheduling. DocsService never had @EnableScheduling, so none of its @Scheduled jobs had ever run. Each was checked against live data and made safe for a first run before switching it on: - careers retention sweep: singleton-locked, 200 per night; 0 applications are past retention today. - talent-alert digest (hourly, SENDS EMAIL): singleton-locked, and a digest now only ever offers roles listed in the last 7 days, so a first run (or any run after an outage) can never mail subscribers a backlog. 0 confirmed subscribers today. - talent-alert purge: singleton-locked and now bounded (500 per night); 1 unconfirmed row today. - careers funnel flush: pod-local counters, deliberately unlocked. - the Compliance engine's own private scheduler is GONE: its jobs are ordinary @Scheduled methods now, so nothing runs on two clocks. Scheduler pool 3 threads (configmap). Schedule triggers ("every January", "every 3 months from January"), stored as every:<months>:<startMonth>, are now run by a nightly singleton-locked sweep (04:10). Each round is a row in hr_compliance_schedule_run, claimed with round happens once whatever the pods or restarts do and resumes where it stopped. Per member it reuses ensureAssigned with the round's first day: on file, already sent, in review, or sent this round (even if since voided) is left alone. Only the org's active human team members are read, a page at a time; never leads. A schedule SAVED mid-round starts with its next round (the round under way is recorded as a baseline), so adding one never mails anybody that night. The editor's save refuses a schedule the sweep cannot run. member.job_changed: heard on security.member.job_changed.> (queue group docs-compliance). Only requirements that carry the trigger are considered, and only when the change brings the member NEWLY into the audience (judged from the previous department / job title in the event) — an everyone audience, or one that already reached them, is not re-sent. TrainingCourse.autoAssignOnJoin is real: on member.activated, ONE assignment row for that member per ACTIVE "assign on join" course whose saved audience includes them and that they have never held. HR's whole-audience Assign is never called, so nobody else is touched. Also: - An executed copy older than the requirement's validity no longer reads as "on file" (the record flipped SATISFIED/EXPIRED and hid a renewal), and the record's assignedAt follows the current assignment, not only the first. - The W-9 library preset row is brought in line with the bundled one (payout setup ONLY, owner 2026-11-12). The stored row still carried commission.credited, which every NEW org would have adopted. No edition bump, so no org is offered anything.
