MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-3498

(motir-core) The E2E job worker sends email through the CONSOLE provider, so no engine-routed send ever reaches the outbox — `jobs-postgres-engine.spec.ts` is red on `main`

Done
Description

Type · test (harness defect) · Repo motir-core · One PR.

Found while running MOTIR-3462's new E2E on branch parent/MOTIR-3415-event-jobs-cutover. Out of that card's scope (notes.html #27), so logged rather than absorbed — but see Resolution: the one-line fix ships in that same PR, because the card's criteria are undischargeable without it.

The defect

playwright.config.ts sets the email sink on the webServer only:

328:        EMAIL_PROVIDER: 'file',
329:        EMAIL_OUTBOX_PATH: EMAIL_OUTBOX_FILE,

The engine's worker is a third process (tests/e2e/_helpers/job-worker-process.ts), spawned with env: { ...process.env, NODE_ENV, E2E_PROD_HARNESS }. It inherits the Playwright runner's env, which carries EMAIL_OUTBOX_PATH (set at playwright.config.ts:150) but not EMAIL_PROVIDER=file.

So a job routed to the Postgres engine sends mail through the dev-console provider. The send genuinely succeeds — the ledger row reaches succeeded — and the message is printed to the worker's stdout instead of being appended to the outbox file. waitForEmail then times out having seen 0 emails total.

Reproduction — on the ALREADY-MERGED spec, with no diff of mine involved

$ PORT=3415 INNGEST_PORT=8415 pnpm exec playwright test \
    tests/e2e/jobs-postgres-engine.spec.ts -g "the dashboard is unchanged"

Error: waitForEmail timed out after 10000ms waiting for an email to
'pge-happy-invitee@example.com'. Outbox path: /tmp/motir-test-emails.jsonl.
Saw 0 email(s) total.
  1 failed

That spec is MOTIR-3427's, it routes email.send to the engine in its own beforeEach, and it is on main. The failure is therefore pre-existing and not caused by the event-cutover branch.

The worker's own stdout in the same run proves the send happened and went to the wrong sink:

[e2e-job-worker] [EMAIL] To: fanout-invitee@example.com
Subject: You're invited to join Fanout Workspace on Motir

Measured on parent/MOTIR-3415-event-jobs-cutover at eb66e701, whose only diff from origin/main@18d60791 is the event-cutover work — none of it touching lib/email.ts, the outbox helper, or playwright.config.ts.

Why it was invisible

The worker process was introduced by MOTIR-3427 for exactly this journey, and its env block already carries a comment saying the flag it does pass (E2E_PROD_HARNESS) was "found by running the spec, not by reading it". The email sink is the same class of omission one flag over — and the lane is push-only in CI, so a red @smoke spec here does not gate an ordinary pull request.

Fix

Mirror webServer.env's two email variables into the worker spawn, so the third process writes to the same sink the runner reads.

Acceptance criteria

  • tests/e2e/_helpers/job-worker-process.ts passes EMAIL_PROVIDER and EMAIL_OUTBOX_PATH to the spawned worker, taking the same values playwright.config.ts gives the webServer.
  • tests/e2e/jobs-postgres-engine.spec.ts -g "the dashboard is unchanged" passes — the assertion that is red today.
  • A comment in the spawn env says WHY, matching the shape of the E2E_PROD_HARNESS note beside it, so the next omission of a webServer-only variable is easier to spot.
  • No change to lib/email.ts, playwright.config.ts's webServer block, or any product code.

Context refs

  • tests/e2e/_helpers/job-worker-process.ts — the spawn env, and the E2E_PROD_HARNESS precedent
  • playwright.config.ts:150, :328-329 — where the outbox path and the provider are set
  • tests/e2e/_helpers/email-capture.ts — the reader, and its default path
  • tests/e2e/jobs-postgres-engine.spec.ts — the merged spec this makes red

Resolution

Fixed on parent/MOTIR-3415-event-jobs-cutover alongside MOTIR-3462, because two of that card's three scenarios assert an engine-routed email and cannot run at all until the sink is right. Surfaced in that pull request's body rather than silently absorbed.