# WhatsApp Message Delivery

## Objective

Reach people on WhatsApp with approved templates, consent checks, and delivery status.

A WhatsApp delivery path that respects the messaging window, uses pre-approved templates, and tracks consent and delivery state.

## Before You Begin

This feature is being added to an application that already exists and already
works. Do not scaffold a new project, and do not assume a blank slate.

Inspect the codebase first and establish:

- The existing application structure and where code of this kind already lives.
- The framework and version in use.
- The existing design system — colours, spacing, typography, and component conventions.
- Existing UI components you can reuse instead of writing new ones.
- The existing database structure, if this feature needs to persist anything.
- The existing authentication and authorization system, if this feature is user-scoped.
- Dependencies already installed, so you don't add a library that duplicates one.
- The existing test setup and conventions.

Only start writing code once you understand the above. If the application
already implements part of this feature, extend it rather than replacing it.

## Implementation Instructions

1. Model the messaging window explicitly. Outside the window only a pre-approved template may be sent; inside it a free-form reply is allowed. Every send must decide which case it is in before it constructs anything.
2. Store approved templates and their parameters in the app, with the language variants each one has been approved for, and validate the parameter set against that record before dispatch rather than discovering a mismatch from a rejection.
3. Record consent per recipient with a timestamp and the source of that consent, and check it at dispatch time. A recipient who has withdrawn consent must be unreachable on this channel from that moment.
4. Send from the app's background-job system and keep a message row with a stable identifier and a delivery state updated only from verified provider callbacks.
5. This brief owns WhatsApp only. If the app also has an SMS path, the choice of which channel a given notification uses belongs to the notification routing layer, not to either delivery integration, so the two do not each decide to send.

## UI and UX Requirements

Match the application's existing design system exactly. Reuse its components,
spacing, and typography. This feature should look like it was always there.

## Responsive Requirements

Works on mobile, tablet, and desktop. Touch targets are large enough to hit on a
phone, and nothing overflows horizontally at 320px.

## Accessibility Requirements

- Fully keyboard navigable.
- Correct semantic elements and ARIA roles.
- Visible focus states.
- Meets WCAG AA contrast.
- Dynamic changes are announced to screen readers.
- Respects prefers-reduced-motion.

## Edge Cases

- Sending free-form content when the conversation window has closed will simply be rejected. Determine the window state from the last inbound message before composing, and fall back to the appropriate approved template.
- Consent and channel eligibility are separate questions. A recipient may have consented and still not be reachable on WhatsApp at that number, and both must be checked before the message is queued.
- A template can be edited, re-approved, renamed, or approved in one language and not another. Pin the version and language a message was built against, and fail loudly on a mismatch instead of sending a message with the wrong or missing parameters.
- Delivery callbacks arrive on a public endpoint, can be replayed, and can arrive out of order. Verify their authenticity, apply them idempotently, and never let an older event overwrite a newer state.
- A recipient who cannot be reached on WhatsApp needs a defined fallback — another channel or a visible failure — decided by the routing layer rather than silently dropped by the integration.
- Retries after a timeout must not produce a second conversation-opening message, which is both confusing and separately billable. Use a stable per-message key.
- Template messages are billed by conversation category. Enforce a per-account ceiling so a retry storm cannot run up an unbounded cost.
- When the provider is unavailable, the triggering action must complete, the message must remain queued, and nothing in the app should claim the recipient has been contacted.

## Testing

Exercise the feature end to end in the running application. Cover every edge case
above, then run the existing test suite and confirm nothing regressed.

## Acceptance Criteria

- [ ] Every send resolves the messaging window and chooses a template or free-form path accordingly.
- [ ] Templates, their parameters, and approved languages are stored and validated before dispatch.
- [ ] Consent is recorded with a timestamp and source and re-checked at dispatch time.
- [ ] Delivery callbacks are authenticated, idempotent, and never regress a message to an older state.
- [ ] Retries do not open a second conversation or send a duplicate message.
- [ ] Unreachable recipients produce a defined outcome handled by the routing layer, not a silent drop.
- [ ] The feature matches the existing design system.
- [ ] No existing functionality is broken.

## Adaptation Rules

- Match the existing design system. Do not introduce a new colour palette,
  spacing scale, or component library.
- Reuse existing components and utilities wherever they fit.
- Follow the naming, file layout, and code style already present.
- Do not upgrade, replace, or remove existing dependencies to make this
  feature fit. Adapt the feature to the app, not the app to the feature.
- Do not break existing functionality. If a change is genuinely required in
  existing code, make the smallest one that works and say so.
- If something in these instructions conflicts with how the application is
  built, follow the application and explain the deviation.

## Final Verification

Before you report the work as done:

1. Re-read the acceptance criteria above and check each one against what you
   actually built.
2. Run the application and exercise the feature end to end.
3. Run the existing test suite and confirm you have broken nothing.
4. Check the feature on mobile, tablet, and desktop widths.
5. Check keyboard navigation and focus handling.
6. Summarize what changed: files added, files modified, and anything you
   deliberately did differently because of how this application is built.

If any acceptance criterion is unmet, fix it before reporting completion.
