# Intercom User and Company Sync

## Objective

Keep Intercom profiles, companies, and plan attributes matching what the app knows.

A sync that pushes app users, their workspaces, and a defined attribute set into Intercom and keeps them current as things change.

## 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. Define the attribute contract before anything else: which fields the app owns and pushes, which fields support owns and the app must never touch, and which are read-only on both sides. Without that line drawn, the sync quietly erases the notes agents rely on.
2. Represent each workspace or organisation as a company and attach every user to the companies they genuinely belong to. A user in three workspaces is one profile with three associations, not three profiles.
3. Key on the app's internal user identifier so a profile survives an email change, and store the provider's identifier back on the app record so later updates target the right profile instead of guessing.
4. Run the initial backfill as a paced background job that honours the provider's rate limits and resumes from where it stopped. Ongoing updates should be incremental and fire only when a synced attribute actually changed.
5. Reuse the app's existing background-job system and credential storage. Do not call the provider from the browser or place the workspace token in client-side configuration, where it can be read and used against the account.

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

- In a multi-workspace account a user must be associated only with the companies they belong to. A wrong association puts one customer's context in front of a conversation about another.
- Attributes that support staff maintain by hand must not be flattened by a stale app value. Push only app-owned fields, and only when they have changed.
- Profiles that were merged, deleted, or deactivated at the provider must be detected and reconciled. Writing blindly to a merged profile either fails or resurrects a record support deliberately cleaned up.
- A backfill will hit rate limits. Pace it, back off on the provider's own signal, and resume rather than restarting the whole run from the beginning.
- Removing a user from a workspace must remove the company association, not merely stop updating it. A stale association is a permanent leak that nobody notices.
- A user who deletes their account must be deleted or anonymised at the provider inside whatever window the app promises its users.
- Restricted content — card details, private message bodies, anything the support team has no business reading — must be excluded from synced attributes explicitly.
- When the provider is unreachable the app must keep working normally. Sync failures belong in a retry queue and an operator alert, never in a user's request path.

## 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 synced attribute has a documented owner and the sync writes only app-owned fields.
- [ ] Users are associated with exactly the companies they belong to, and removals propagate.
- [ ] Profiles are keyed on an internal identifier and the provider's identifier is stored back on the record.
- [ ] Backfills pace themselves against rate limits and resume after an interruption.
- [ ] Merged, deleted, and deactivated provider profiles are reconciled rather than blindly rewritten.
- [ ] Provider downtime never blocks, slows, or fails a user-facing request.
- [ ] 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.
