# Google Calendar Event Creation

## Objective

Turn app records into Google Calendar events with attendees, reminders, and links.

An authorized per-user connection to Google Calendar that creates and updates events from app records and keeps the two linked.

## 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. Authorize each user individually and store the resulting tokens encrypted and server-side only. Request the narrowest calendar scope that supports writing events, and never place any credential where client-side code can read it.
2. Ask the user which calendar to write to during setup and store that choice per connection. Do not assume the primary calendar, because many people keep work bookings on a secondary or shared one.
3. Store every event time as an instant plus the named time zone it was entered in, and send both. A time expressed only as an offset breaks the moment daylight saving shifts or the event is moved.
4. Send an idempotency-style stable identifier derived from the app record with every create, and record the returned event reference against the record. On retry, look up that reference and update rather than creating a second event.
5. Perform all calendar calls through the app's existing background-job system so a slow or failing Google response never blocks the user's save. Show the sync state on the record instead.

## 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 user with several calendars will otherwise get bookings on the wrong one. Let them choose the target calendar per connection, show which calendar is in use on the record, and re-prompt if that calendar is later deleted or no longer writable.
- Times sent without an explicit named zone drift after a daylight saving change and land an hour off for recurring bookings. Persist the zone the event was authored in alongside the instant, and render it to viewers in their own zone.
- A retry after a timeout can create a duplicate event because the first attempt may have succeeded unseen. Store the provider's event reference against the record on first success, and on any retry reconcile against that reference before creating anything.
- Attendees, recurrence rules, and calendar sharing permissions change independently of the app. Handle an attendee who declines, a recurring series edited at the provider, and a token whose granted access has been narrowed, by surfacing the mismatch on the record rather than overwriting the user's calendar.
- An event moved or deleted directly in Google leaves the app's copy wrong. Detect the missing or changed event on the next sync, mark the local record as diverged, and ask the user whether to recreate or unlink rather than silently rewriting their calendar.
- Access tokens expire and refresh tokens get revoked when a password changes or an admin removes the app. Refresh proactively, and on a permanent authorization failure mark the connection as disconnected and prompt the user to reconnect instead of retrying forever.
- Google rate limits per user and per project. Back off with jitter on throttling responses, queue rather than burst when a bulk action would create many events, and never retry a validation rejection.
- When Google Calendar is unavailable, the app must still accept the booking. Save the record, queue the calendar write, and show a pending sync state with a clear retry, rather than failing the user's action.

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

- [ ] Each user authorizes their own connection, and tokens are stored encrypted server-side only.
- [ ] The target calendar is chosen explicitly and recorded per connection.
- [ ] Event times are stored and sent with an explicit named time zone.
- [ ] A retried create reconciles against the stored event reference and never produces a duplicate.
- [ ] Events changed or deleted in Google are detected and flagged on the linked record.
- [ ] Expired or revoked authorization marks the connection disconnected and prompts a reconnect.
- [ ] A Google outage leaves the app usable, with the calendar write queued and visibly pending.
- [ ] 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.
