Back to DevLog

Fixed three classes of orphaned rows from missing tenant_id

2 min read

I found that self-registering customers never got assigned to a tenant. POST /api/register was the only INSERT INTO users in the codebase that omitted tenant_id, so every user who signed up became permanently invisible to the tenant admin.

The registration bug

getTenantFromHeaders() already existed and the client already sent the tenant headers on every request. The bug was that register ignored them. I added tenant resolution to the endpoint and made it fail closed. A user who cannot be assigned is not created.

The eBay submission bug

During the audit I found a second orphan of the same class. POST /api/ebay/winner-submission also never set tenant_id, while every read, update, and delete of ebay_winner_submissions filters by it. Every auction winner who used that form was invisible to the seller.

That form uses raw axios and bypasses the interceptor that adds tenant headers, but the component already had tenantId from useConfig. I passed it in the request body and verified it server-side against the tenants table.

The email log bug

email_logs.tenant_id was NULL on all 69 rows since migration 031 added the column. logEmail() never wrote it. I threaded tenant through the single sendEmail() funnel across 14 call sites.

I wrote migration 032 to backfill the recoverable rows. 52 of 69 have a deterministic tenant. The other 17 cannot be assigned because the recipient address is ambiguous or the row is seed data.

What I did not infer

I never infer tenant from the recipient email address. claudeweidner2013@gmail.com is simultaneously user 47 in tenant 21 and the admin of tenant 20. A recipient-based rule would have silently mis-assigned those 5 rows. The backfill leaves them NULL.

The portalUrl in email metadata comes from the server CLIENT_URL env var, not the request, so it is not evidence of which tenant site a user was on.

Share this post