gigafibre-fsm/services/targo-hub/lib
louispaulb c0ca5feb6f feat(campaigns): gift redirect wrapper — own expiry + reusable links
Each campaign recipient now gets a short opaque token (10 base64url
chars, ~60 bits entropy). The email contains

  https://msg.gigafibre.ca/g/<token>

which 302-redirects to the underlying Giftbit shortlink — but ONLY if
the recipient hasn't passed our own expires_at and we haven't revoked
the token. This gives us two new operational capabilities:

1. End-date control independent of Giftbit. The wizard now has a
   "Expiration interne (jours)" field (default 90) that sets our
   own deadline. Useful when the Giftbit gift is valid 12 months
   but the campaign offer should expire in 30 days.

2. Reuse of unredeemed gifts. After our expiry, the old wrapper
   stops working but the Giftbit URL is still valid on their side.
   Pasting that same gift_url into a new campaign (via the manual-add
   dialog) generates a NEW token pointing to the same Giftbit gift —
   the original recipient's old wrapper URL says "expired", the new
   recipient gets a fresh window.

Per-recipient new fields:
- gift_token            short ID used in the wrapper URL
- gift_expires_at       ISO timestamp of our cutoff
- gift_revoked          manual kill-switch (false by default)
- gift_redirected_count clicks that successfully reached Giftbit
- gift_first_redirected_at  first successful redirect timestamp

Routing:
- GET /g/:token  — public, validates and 302s (or expired-page)
- Mailjet click event handler updated to recognise wrapper URLs
  alongside legacy gft.link/giftbit.com URLs.
- /view (browser fallback for in-email rendering) also wraps the
  gift link so expiry/revoke is honoured consistently.

Bootstrap rebuilds the in-memory token→recipient index by scanning
all campaign JSONs on startup — no separate index file to keep in
sync.

CSV report adds gift_token, gift_expires_at, gift_revoked,
gift_redirected_count, gift_first_redirected_at.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:15:43 -04:00
..
ui refactor(targo-hub): extract ui/ kit, migrate tech-mobile to it 2026-04-22 22:47:19 -04:00
acceptance.js refactor(targo-hub): add types.js, migrate acceptance+payments, drop apps/field 2026-04-22 23:18:25 -04:00
address-search.js refactor: extract composables from 5 largest files — net -1950 lines from main components 2026-04-08 17:57:24 -04:00
address-validate.js fix(ops/dispatch): /desk/<DocType>/ broken URL → /app/<slug>/ + add /address/validate hub 2026-05-08 11:01:32 -04:00
agent-flows.json refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
agent-tools.json refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
agent.js refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
ai.js refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
auth.js feat(hub+ops): user invite flow sends temp password via Mailjet + dev .env.example 2026-05-05 19:50:06 -04:00
campaigns.js feat(campaigns): gift redirect wrapper — own expiry + reusable links 2026-05-22 10:15:43 -04:00
checkout.js feat: contract → chain → subscription → prorated invoice lifecycle + tech group claim 2026-04-22 20:40:54 -04:00
config.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
contracts.js fix(chain+subs): safe job-delete, plan_name from Quotation, bi-dir sub link 2026-04-23 10:19:56 -04:00
conversation.js refactor(targo-hub): add erp.js wrapper + migrate 7 lib files to it 2026-04-22 23:01:27 -04:00
device-extractors.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
device-hosts.js refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
devices.js feat: contract → chain → subscription → prorated invoice lifecycle + tech group claim 2026-04-22 20:40:54 -04:00
dispatch.js fix(chain+subs): safe job-delete, plan_name from Quotation, bi-dir sub link 2026-04-23 10:19:56 -04:00
email-templates.js refactor: extract composables from 5 largest files — net -1950 lines from main components 2026-04-08 17:57:24 -04:00
email.js feat(hub): gift-campaign module — CSV parse, customer match, async send + webhook 2026-05-21 19:07:40 -04:00
erp.js refactor(targo-hub): add erp.js wrapper + migrate 7 lib files to it 2026-04-22 23:01:27 -04:00
flow-api.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
flow-runtime.js docs: reorganize into architecture/features/reference/archive folders 2026-04-22 11:51:33 -04:00
flow-templates.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
helpers.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
ical.js refactor(targo-hub): add erp.js wrapper + migrate 7 lib files to it 2026-04-22 23:01:27 -04:00
magic-link.js refactor(targo-hub): add erp.js wrapper + migrate 7 lib files to it 2026-04-22 23:01:27 -04:00
modem-bridge.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
network-intel.js refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
oktopus-mqtt.js refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
oktopus.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
olt-snmp.js feat: contract → chain → subscription → prorated invoice lifecycle + tech group claim 2026-04-22 20:40:54 -04:00
otp.js refactor(targo-hub): add erp.js wrapper + migrate 7 lib files to it 2026-04-22 23:01:27 -04:00
outage-monitor.js refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
payments.js refactor(targo-hub): add types.js, migrate acceptance+payments, drop apps/field 2026-04-22 23:18:25 -04:00
pbx.js refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
poller-control.js feat: contract → chain → subscription → prorated invoice lifecycle + tech group claim 2026-04-22 20:40:54 -04:00
portal-auth.js feat(portal): passwordless magic-link login — retire ERPNext /login 2026-04-22 13:25:28 -04:00
project-templates.js fix(contracts): create pending Service Subscription on signing + test templates 2026-04-23 10:03:49 -04:00
provision.js chore(hub): gate Oktopus integration behind OKTOPUS_DISABLED flag 2026-05-04 10:34:36 -04:00
referral.js refactor(targo-hub): add erp.js wrapper + migrate 7 lib files to it 2026-04-22 23:01:27 -04:00
reports.js refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
sse.js refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
tech-absence-sms.js refactor(targo-hub): add erp.js wrapper + migrate 7 lib files to it 2026-04-22 23:01:27 -04:00
tech-mobile.js refactor(targo-hub): add types.js, migrate acceptance+payments, drop apps/field 2026-04-22 23:18:25 -04:00
telephony.js refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
traccar.js feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
twilio.js refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
types.js refactor(targo-hub): add types.js, migrate acceptance+payments, drop apps/field 2026-04-22 23:18:25 -04:00
vision.js feat(tech-mobile): SPA redesign with tabs, detail view, notes, photos, field-scan 2026-04-22 22:19:00 -04:00
voice-agent.js refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00