Skip to content

Redirect Reconnect Flow To Successor Provider When Configured#604

Open
boris-careev wants to merge 10 commits into
mainfrom
boris-provider-successor-mdhui-v2
Open

Redirect Reconnect Flow To Successor Provider When Configured#604
boris-careev wants to merge 10 commits into
mainfrom
boris-provider-successor-mdhui-v2

Conversation

@boris-careev
Copy link
Copy Markdown
Contributor

@boris-careev boris-careev commented May 12, 2026

Overview

When a provider has a successorID configured, the existing Reconnect button now silently targets the successor provider instead of the legacy one - no additional UI or user-facing wording is introduced.

Changes:

  • SingleExternalAccount: Only the Reconnect link is shown for accounts whose provider has a successorID, regardless of the account's sync status (except while the account is being deleted or refreshed). Previously it only appeared on unauthorized accounts.
  • ExternalAccountList: reconnectAccount now resolves the provider ID as successorID ?? id, so the connectExternalAccount call targets the successor when one is configured. The backend is then responsible for detecting the predecessor account and cleaning it up after the successor connection succeeds.

Security

Consider potential security impacts and complete the following checklist.
REMINDER: All file contents are public.

  • I have ensured no secure credentials or sensitive information remain in code, metadata, comments, etc.
    • Please verify that you double checked that .storybook/preview.js does not contain your participant access key details.
    • There are no temporary testing changes committed such as API base URLs, access tokens, print/log statements, etc.
  • These changes do not introduce any security risks, or any such risks have been properly mitigated.

These changes only alter which provider ID is passed to the existing connectExternalAccount API call. No new endpoints, no credentials, no data exposure. The successor ID comes from the provider model already returned by the API.

Testing

Consider whether the changes might have device-specific behaviors (screen padding, new APIs, etc.) and check one of the following boxes:

  • This change can be adequately tested using the MDH Storybook.
  • This change requires additional testing in the MDH iOS/Android/Web apps. (Create a pre-release tag/build and test in a ViewBuilder PR.)

To test, configure a provider with a successorID in the backend and verify:

  1. A connected account for that provider shows the Reconnect button only (no Refresh link), regardless of its sync status.
  2. Clicking Reconnect initiates the connection flow against the successor provider (confirm via network tab: externalaccountproviders/{successorID}/connect).
  3. After successful connection, the backend deletes the predecessor account (backend change tracked separately).
  4. Providers without a successorID retain existing reconnect behavior unchanged.

Documentation

Consider whether there are any documentation impacts and check one of the following boxes:

  • I have added relevant Storybook updates to this PR.
  • If this feature requires a developer doc update, I have tagged @CareEvolution/api-docs.
  • This change does not impact documentation or Storybook.

Reviewers

Assign to the appropriate reviewer(s). Minimally, a second set of eyes is needed ensure no non-public information is published. Consider also including:

  • Subject-matter experts
  • Style/editing reviewers
  • Others requested by the content owner

Consider "Squash and merge" as needed to keep the commit history reasonable on main.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the external account reconnect experience so that when an external account provider is configured with a successorID, reconnect silently targets the successor provider instead of the legacy provider.

Changes:

  • Hide Refresh and show Reconnect for accounts whose provider has a successorID (with an exception for delete-in-progress).
  • Update reconnect behavior to call connectExternalAccount(successorID ?? id).
  • Add Storybook preview data/stories to exercise successor-provider scenarios.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/components/presentational/SingleExternalAccount/SingleExternalAccount.tsx Adjusts Refresh/Reconnect visibility rules, including successor-provider behavior.
src/components/presentational/SingleExternalAccount/SingleExternalAccount.stories.tsx Adds successor-provider Storybook scenarios for the presentational component.
src/components/container/ExternalAccountList/ExternalAccountList.tsx Reconnect now targets successorID ?? id; adds preview state for successor demo data.
src/components/container/ExternalAccountList/ExternalAccountList.stories.tsx Adds a successor-provider story (but currently has issues with args wiring / previewState values).
src/components/container/ExternalAccountList/ExternalAccountList.previewdata.tsx Adds preview data including providers with successorID.
package.json Bumps version to a prerelease identifier for this change set.
package-lock.json Keeps lockfile version in sync with package.json version change.
Comments suppressed due to low confidence (2)

src/components/container/ExternalAccountList/ExternalAccountList.stories.tsx:70

  • The Live story is not configuring its own args: it declares export const Live = ... but then assigns to Default.args, overwriting the Default story instead. Update this to set Live.args (and keep Default.args intact) so Storybook renders both stories as intended.
export const Live = Template.bind({});
Default.args = {
    externalAccountProviderCategories: ["Provider", "Health Plan", "Device Manufacturer"]
};

src/components/presentational/SingleExternalAccount/SingleExternalAccount.tsx:88

  • Using href="javascript:{}" for the Reconnect control is brittle (can be blocked by CSP) and is not ideal for accessibility/semantics. Prefer rendering this as a <button type="button"> (or the existing UnstyledButton) so it behaves like an action rather than a navigation link.
					<p>
						<a href="javascript:{}" onClick={() => props.onReconnectAccount(props.externalAccount)}>
							<FontAwesomeSvgIcon icon={faRepeat} /> {language("external-account-reconnect")}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +61 to +65
export const WithSuccessorProvider = Template.bind({});
WithSuccessorProvider.args = {
previewState: "withSuccessor",
externalAccountProviderCategories: ["Provider"]
};
Comment on lines +84 to 86
{(getStatus() === "unauthorized" || (!!props.externalAccount.provider.successorID && getStatus() !== "deleting")) &&
getStatus() !== "fetchingData" && getStatus() !== "deleting" &&
<p>
Comment on lines 78 to 80
<p>
<a href="javascript:{}" onClick={refresh}>
<FontAwesomeSvgIcon icon={faRepeat} /> {language("external-account-refresh")}
@aws-amplify-us-east-1
Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-604.d1xp2kmk6zrv44.amplifyapp.com

@boris-careev boris-careev mentioned this pull request May 12, 2026
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants