Skip to content

Notification Conventions

Status: Active Last reviewed: 2026-06-30

How TwoMore classifies, delivers, and gates push notifications. Covers the 정보성 vs 광고성 split (정통망법 §50), Android channel setup, the iOS soft-prompt timing rule, and server-enforced frequency caps. Rationale and history live in CLAUDE.md; the machine-enforced subset is in AGENTS.md.

Service vs marketing (§50)

  • Push notification kind → classify as 정보성 (service) or 광고성 (marketing) at design time per 정통망법 §50. Service pushes (RSVP, match start, dues, scores, attendance) are EXEMPT from §50 — no marketing consent required. Marketing pushes require (a) active grant for marketing_push purpose in user_consent, (b) "(광고)" prefix in title, (c) 1-tap unsubscribe deep-link, (d) 광고 prefix in the send-push edge function payload. Night-time (21:00–08:00 KST) marketing requires the SEPARATE marketing_push_night consent grant (§50-8). The 13-category signal_category enum (session / matchup / rsvp / dues / club / social / progression / rating / trust / payment / interclub / chat / system) is all 정보성 — no §50 plumbing needed for any of these categories.

Android channels

  • Android notification channels → MUST exist before send-push references them. The 13-channel set (session / matchup / rsvp / dues / club / social / progression / rating / trust / payment / interclub / chat / system) is created in notification.expo.ts via ensureAndroidChannels(). Adding a 14th category: add to signal_category enum first (migration), then add the channel config to the adapter, then bump the app version and trigger a new EAS build — channel config is native and is NOT OTA-able.

Permission soft-prompt

  • Permission soft-prompt → NEVER request notification permission on cold-mount. Use PushPermissionSoftPromptSheet from @twomore/sessions, triggered after the user's first RSVP success. iOS dismissal is one-shot — burning the prompt at cold-mount means the user can never re-enable without going to Settings manually.

Frequency caps

  • Frequency caps → signals_pick_pushable enforces 10/day per user + 3/day per (user, category) with a critical-signal bypass. Never override the cap at the call site. New high-frequency signal types must respect the cap or users will uninstall.

See also

  • AGENTS.md — COMP-7, ARCH-9 (machine-enforced notification subset).
  • Conventions › Korean Market — marketing push §50 title format, consent grants, and Alimtalk rules.
  • CLAUDE.md — orchestration core + the pointer index back to this doc.

Markdown remains the source of truth. Run yarn docs:check before handoff.