# Airtable Record Sync

## Objective

Create and update Airtable records with mapped fields, links, and attachments intact.

A configured sync of app records into a selected base and table, resolving linked records and transferring attachments.

## 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. Read the selected table's fields and their types at setup, and read them again before a mapping is used, rather than trusting a mapping saved months ago against a schema somebody has since changed.
2. Validate every value against its destination field type before sending, and check option values against that field's current choices so a write neither fails nor quietly expands the list.
3. Resolve linked records by looking up the related table first and reusing the match. Create a related record only when the lookup finds nothing, never once per write.
4. Serve attachments from a signed URL that lives only long enough for the provider to fetch the file, and revoke it once the fetch is confirmed. Do not make the file publicly readable to complete the transfer.
5. Carry a stable app identifier in a dedicated field and upsert on it. Google Sheets Row Sync and Notion Database Sync solve the same mapping and idempotency problem against other destinations, so share the mapping and queue layer and vary only the destination adapter.

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

- A value of the wrong type is rejected outright, and a single-select value absent from the field's options either fails or expands the list. Validate before sending, and make expanding a list a deliberate setting rather than a side effect.
- Linked-record fields take record identifiers, not text. Writing the display name creates a new related record every time, and a month later the related table is full of near-duplicates.
- Fields get renamed, retyped, and deleted by whoever owns the base. A mapping must be revalidated, and when it no longer resolves the destination pauses with a message naming the field rather than skipping it silently.
- Attachments are fetched by the provider from a URL the app supplies. That URL must be signed, short-lived, and revoked after the fetch, or the app has published a permanent public link to customer data.
- Rate limits are enforced per base and are low. A backfill must pace itself, batch records, and back off when refused rather than saturating the limit and starving ordinary writes.
- Without an upsert key a retried job creates a second record. The key belongs in its own field on the destination, not inferred from a name or an email address.
- Bases enforce record and attachment size limits. A record that exceeds them must be reported as too large rather than retried indefinitely.
- If the connection is revoked or the base is deleted, the destination must be disabled and the owner told, not left retrying against a base that no longer exists.

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

- [ ] Field types and option values are validated against the live schema before every send.
- [ ] Linked records resolve to existing rows and are created only when no match exists.
- [ ] A stable key field makes repeated runs idempotent, and no retry produces a duplicate record.
- [ ] Attachment URLs are signed, short-lived, and revoked after the provider fetches them.
- [ ] Backfills stay within the provider's rate limits and back off instead of failing.
- [ ] Schema changes and revoked access pause the destination with a message naming the cause.
- [ ] 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.
