# HubSpot Lead Capture

## Objective

Create or enrich HubSpot contacts and link them to companies, deals, and source context.

A capture path that matches or creates a HubSpot contact and company, associates them, and attaches how the lead arrived.

## 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. Search for an existing contact and an existing company before creating either, matching the contact on the normalized email and the company on the domain, and associate to what you find rather than adding a parallel record.
2. Write only properties the app is the source of truth for. Skip blanks entirely, and treat any property a salesperson can edit as theirs unless an admin has explicitly opted into letting the app overwrite it.
3. Capture the source context the app knows and CRM users do not — the plan, the referring campaign, the signup path, the in-app actions taken — because that is the part of the record that justifies the integration.
4. Run the whole capture in the app's existing background-job system, and record a per-lead sync status with the failure reason. The original conversion must be committed and confirmed to the user before any CRM call is attempted.
5. Do not let this feature and any other CRM sync in the app both claim the same lead. Designate one CRM as the destination for a given lead type in configuration, so a signup does not appear as three unrelated records across three systems.

## 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

- Creating a contact without searching first produces duplicates that sales teams then have to merge by hand. Search on the normalized email, and search the company on domain, before any create.
- Sales teams correct and enrich records constantly. An update that writes every mapped property, including empty ones, replaces a hand-verified phone number with nothing — send only non-empty values for properties the app owns.
- A connection can reach more than one CRM account, and pipelines and their stages differ between them. Pin the account, pipeline, and stage at configuration time and validate they still exist before each write.
- Custom properties have types, allowed option values, and can be archived. A string written into a numeric or enumeration property fails, so validate the mapping against the current property definitions and pause with a named error rather than dropping the lead.
- A CRM failure must never roll back the app-side conversion. Persist the lead locally, mark the sync failed with its reason, make it retryable, and leave the user's signup or purchase intact and confirmed.
- Token expiry, revoked scopes, and rate limits all surface as failures that look alike. Distinguish them: refresh on expiry, mark the connection broken on revocation, and back off and requeue on rate limiting.
- Associating a contact to the wrong company is worse than leaving it unassociated. Where the domain match is ambiguous — shared mail domains, contractors, subsidiaries — leave it unassociated and flag it for a human.
- While the provider is down, capture must stay open. Queue the work, show pending status on the lead, and never present the outage to the person filling in the form.

## 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

- [ ] Existing contacts and companies are found and reused instead of duplicated.
- [ ] Blank and app-unowned values never overwrite CRM data.
- [ ] Records are created in the configured account and pipeline, validated before each write.
- [ ] Property type mismatches and archived properties pause the mapping with a named, actionable error.
- [ ] A failed sync leaves the original conversion complete and is visible and retryable.
- [ ] Ambiguous company matches are left unassociated and flagged rather than guessed.
- [ ] Only one CRM destination is configured per lead type.
- [ ] 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.
