fix(workers): scope notification template lookup; audit from_trusted #195
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/pms-261-worker-from-trusted-audit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Step 6 of PMS-255 per-user isolation. Audits the cross-tenant background workers (calendar reminder, SLA sweep, billing recurring, RMM ingest, notification dispatcher) and every
from_trustedescape hatch against the fail-closed RLS policy (migration 038).Behavioral fix:
NotificationsService::dispatchfetched the rule'snotification_templatesrow on the bare pool with noapp.current_tenantGUC.notification_templatescarries atenant_idand is covered by the fail-closed policy, so under an unprivileged (NOBYPASSRLS) connection that read matches zero rows and silently drops the template, degrading to the default subject/body. The lookup now runs throughbegin_with_tenant(tenant_id); thetemplate_idcomes off this tenant's own rule, so the row resolves under the same tenant.Audit findings (no behavior change, SAFETY notes only): each worker already wraps its per-tenant unit of work (
claim_reminder,claim_sla_notification,dispatch,generate_due_recurring_invoices) inbegin_with_tenant, so the GUC is set to exactly the tenant being processed. The cross-tenant enumeration scans incalendar::due_remindersand the SLA sweep are deliberately unscoped (they projecttenant_idoff DB rows to drive the loop) and run as the BYPASSRLS migration role; both now carry a note explaining the posture and the NOBYPASSRLS migration path. Everyfrom_trustedsite (calendar/sla workers, portal ticket bridges, tenants super-admin handlers, the tenants create path, and the legacy auth dispatch/audit sites) now carries a current// SAFETY (PMS-261):note tying the trusted tenant to an authenticated or DB-derived source.Adds tests/worker_tenant_isolation.rs: drives the dispatcher (the shared worker fan-out) for tenant A while tenant B holds a matching rule plus template, and asserts the worker neither reads tenant B's rule nor writes a notification row under tenant B, and that tenant A's row resolves against tenant A's own template.
#PMS-261
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com