Skip to content

Live (part 1) — notify + email on AUTO-MATCH linked

Goal

Part 1 of the "make it live" initiative (T-037 = umbrella + full audit). When the auto-matcher LINKS a tx↔invoice, fire the existing notifyPaymentMatched (in-app + email at severity ≥ warning). Today applyVendorLink (matching/vendorMatch.server.ts ~82) only console.logs. #1 "feels not live" gap — the producer already exists; just call it from the auto-link path (and pick a severity that emails). Recipients: ACCOUNTING_NOTIFICATION_ROLES.

Log

  • 2026-06-14 created (T-037 split, owner).

Decision log

2026-07-09 — re-scoped (half shipped along the way) + routed to Accounting (Diagnostics)

  • ✅ Read AGENTS.md. Backlog-review probe (2026-07-09): notifyPaymentMatched IS now wired on the transaction-PATCH path (pages/api/accounting/transactions/[id].ts — one notification per NEWLY matched invoice), so half this task shipped incidentally. Remaining scope = the AUTO-matcher path only: applyVendorLink / the matching libs still contain zero notify calls — an auto-link lands silently. Owner routing (2026-07-09, verbatim): "route T-038, T-040, T-072, T-083, T-051" per the review recommendations → Accounting (Diagnostics) (same producer family as T-040/T-041); queue behind their active T-156/157/158 cluster.
  • Source: EOP Local Assistance (fork) · session edb0abc7-6373-449b-8e31-379fd38d391b

2026-07-10 — BUILT + SHIPPED (owner: "proceed") — status → done

  • ✅ Read AGENTS.md · checked the board by scope (no dup — T-162's waves govern consumption, not producers; verified zero notify calls in the matcher pre-change) · tracking T-038.
  • Source: Accounting (Diagnostics) · https://claude.ai/code/session_01G58Y71noihrYCDEDMexmea
  • What landed: new producer notifyVendorAutoMatched (notify.ts, exported via the barrel) + the call in applyVendorLink (vendorMatch.server.ts) — the single link point both matcher directions (invoice-side + transaction-side) funnel through, so one wire-up covers every auto link, including the periodic re-run sweep in hooks.server.ts.
  • Design decisions (why not exactly the old goal text):
  • The goal said "fire the existing notifyPaymentMatched" — that producer is CUSTOMER-invoice shaped (projectId/year/invoice-preview URL) and severity info (never emails). The vendor matcher links VENDOR invoices to debits; forcing the customer shape would produce broken action links. Built the automatic sibling instead, copying the one-per-newly-linked pattern and failure tolerance per the 2026-07-09 re-scope ("copy its pattern, don't re-invent").
  • Type reused (payment_status), no new taxonomy entry — slots into T-162's preference matrix as-is; zero coordination burden on User Management.
  • Severity warning → in-app AND email (the task's stated goal: "in-app + email at severity ≥ warning") — an automatic ledger change with no human in the loop is what the offline-reach layer exists for.
  • Message is self-contained (amount, tx id, vendor, invoice, matched fingerprint) per the hide-and-seek rule fixed in T-162; action link → /accounting?tab=transactions.
  • Notify failure never unwinds the link (try/catch + log; the link is the source of truth).
  • Non-link outcomes (ambiguity / new vendor) deliberately stay silent here — they are T-041's suggestion notifications.
  • Verification: 5 new tests (vendorMatchNotify.test.ts): one-candidate → exactly one notification with full payload (both directions); ambiguous + new-vendor → silent; notify failure → link survives. Suite 653/653; unfiltered tsc clean.
  • Commit SHAs (append-only): this ship commit (T-038 in subject; merged via PR).
  • Deploy: pending (main 🟡🟡 manual — done means merged, not deployed).
  • Blast radius: notification volume only — accounting roles now receive one warning-severity notification (+ email) per vendor auto-link. No matcher logic, amounts, or data shapes changed.