Switchbordswitchbord
v0.16.06

v0.16.06

Operator-only campaign client context lands in the inbox bio pane — resort, target dates, gross price quoted, family, last reservations, and a host-validated Travio pratica link.

What's new


  • The inbox bio pane now shows campaign-specific Travio context for each recipient: resort name, target travel dates, the most recent gross price quoted, family composition (adults + children count and ages), and recent reservations. Each pratica is a one-click jump into Travio for the operator.
  • Translated for en, it, fr, de, es, pt, zh via a dedicated inbox.campaignContext next-intl namespace. Dates render in Europe/Rome regardless of browser timezone so the same trip looks the same to everyone.

Privacy & security


  • Operator-only PII surface, product-approved for authorized operators.
  • Campaign PII is kept out of the inbox IndexedDB cache; the bio card is hydrated only on direct conversation fetch and mark-read.
  • Server-side snapshot deletions clear the bio card immediately — the reducer distinguishes list-refresh nulls from authoritative direct-hydration nulls so stale PII never outlives its source row.
  • Travio links are validated against the allow-listed origin and a strict /pratiche/detail/\d+ path; embedded credentials, ports, query, and hash are all rejected.

Data hardening


  • New campaign_recipient_client_contexts table with workspace-scoped RLS (SELECT-only for authenticated), strict check constraints on currency / pratica id / lengths / dates ordering, and unique indexes on (workspace_id, campaign_recipient_id) and (workspace_id, campaign_id, contact_id).
  • Sanitizer clamps adults / children counts to 50, child ages to 0–17 with a ≤ 20 array cap, and drops any non-numeric pratica id.

Verification


  • pnpm --filter @repo/database typecheck
  • pnpm --filter @repo/database test
  • pnpm --filter app exec tsc --noEmit
  • pnpm --filter app test
  • pnpm exec biome check