# DocuSign Signature Request

## Objective

Send documents for signature through DocuSign and track every recipient's state.

An envelope-based signing flow that sends app documents to DocuSign, mirrors recipient and envelope status, and stores the completed files.

## 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 request in the app first: the document, the ordered recipients with their roles, and the envelope's own lifecycle state, so the app can answer where a signature stands without calling the provider.
2. Prefer a configured template with named roles and named fields over positioning signature fields at fixed coordinates. Coordinates break the moment the document's layout or page count changes, and they break silently.
3. Store the envelope identifier against the app record when the send is confirmed, and make sending idempotent on that record so a retry after a timeout resumes tracking rather than sending the customer a second copy.
4. Verify every status callback's authenticity before acting on it, ignore callbacks for envelopes the app does not recognise, and treat repeated deliveries of the same status as one event because the provider will retry.
5. Store completed documents and their audit certificates in the app's existing file storage behind the same permission checks as the record they belong to, and serve them through short-lived links rather than a permanent public URL.

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

- Recipients need roles, an explicit routing order, and any required identity verification set before the envelope is sent. Getting the order wrong sends the document to a counter-signer before the person whose signature it depends on.
- Templates change. Role names and field names must be resolved against the current template and the send refused with a clear error when a role no longer exists, rather than sending an envelope with an unassigned signer.
- Callbacks are unauthenticated until proven otherwise and arrive more than once, out of order, and sometimes long after the fact. Verify the signature, key on the envelope and event, and ignore a status older than the one already recorded.
- Envelopes end in states other than completed: declined, voided, expired, and corrected all need a represented state in the app and a defined effect on whatever the signature was gating.
- Signed documents and audit trails are among the most sensitive files the app holds. They must inherit the record's permissions, not be reachable by anyone with a link, and any temporary link must expire.
- The provider will rate-limit and will occasionally be unavailable. Queue the send, back off, and show the user that the request is pending rather than reporting a signature request that was never actually created.
- The stored authorization expires and must be refreshed before it lapses. A refresh failure should mark the connection as needing reconnection and pause sends, not fail each envelope individually with an unhelpful error.
- If callbacks stop arriving, envelopes will sit at a stale status forever. Reconcile open envelopes on a schedule so status is eventually correct even when a webhook was lost.

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

- [ ] The app holds its own record of the envelope, its recipients, and their states, readable without contacting the provider.
- [ ] Signature placement uses templates with named roles and fields rather than fixed coordinates.
- [ ] Sending is idempotent per record, so a retry after a timeout never produces a second envelope.
- [ ] Status callbacks are authenticity-verified, deduplicated, and safe to receive out of order.
- [ ] Declined, voided, expired, corrected, and completed envelopes each have a represented state and a defined consequence.
- [ ] Completed documents and audit certificates are permission-checked and served through expiring links.
- [ ] A scheduled reconciliation corrects any envelope whose callback was lost.
- [ ] 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.
