Skip to content

Release 1.98.0 to master - #1967

Merged
krystophv merged 43 commits into
masterfrom
release-1.98.0
Jul 2, 2026
Merged

Release 1.98.0 to master#1967
krystophv merged 43 commits into
masterfrom
release-1.98.0

Conversation

@clintonium-119

Copy link
Copy Markdown
Member

No description provided.

darinkrauss and others added 30 commits January 8, 2026 00:35
- Add Oura authentication
- Add provider flag to require the patient must be logged in to connect
- Add provider flag to require an existing data source to connect
- Filter active providers for only allowed connections based on above
- Add new accept status to the OAuth workflow for UI before authorization
- Add Oura logo
Restructured the consent dialog layout for full-width dividers
and proper content alignment per design specifications.
- Moved padding from wrapper to individual sections
(header/content/footer)
- Image now sits inline with subheading only, body text below full-width
- Right-justified the "I understand" button in footer
Wrapped first consent paragraph with Trans component to make
"Tidepool's Privacy Policy" a clickable link.
- Added URL_PRIVACY_POLICY import from constants
- Used html.oauth-accept-privacy-message i18n key for Trans
- Updated message rendering to handle both string and JSX
Added check to ensure return_url starts with '/' before redirecting,
protecting against potential open redirect attacks via crafted URLs.
Improved return_url validation with isSafeReturnUrl helper to prevent
open redirect attacks. Added test coverage for new provider features.
- Added isSafeReturnUrl with checks for protocol-relative URLs
- Added oura provider to test expectations
- Added tests for requiresLoggedInUser filtering
- Added tests for requiresExistingDataSource filtering
- Added test for accept status early return in popup
- Updated AGENTS.md with targeted test running guidance
Fixed tests to account for oura's requiresLoggedInUser and
requiresExistingDataSource restrictions. Updated AGENTS.md
to use .only for isolating Karma tests instead of --grep.
…scripting

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
The scroll handler only sets the ConsentRead flag when the user scrolls
to the bottom of the consent document. If the content is short enough
that the container isn't scrollable, the scroll event never fires and
the user has no way to enable the consent checkbox.

Attach a ref to the scroll container and run an effect that compares
scrollHeight to clientHeight; if the content fits without scrolling,
mark the current step's ConsentRead field as true. Guarded against
re-setting an already-true value to avoid a Formik update loop.
…nsent

- When the consent document is short enough that the container isn't
  scrollable, the scroll handler never fires and the consent checkbox
  stays disabled. Capture the scroll container via a useState setter
  ref so MUI Portal's deferred child mount triggers a re-render, then
  in a useEffect mark the current step's ConsentRead as true if
  scrollHeight fits within clientHeight. Guarded against already-true
  values (prevents Formik update loops) and zero-height layout (jsdom).

- Include the name field in the primary schema for child patients on
  personal accounts (previously only enforced for youth).
@clintonium-119

Copy link
Copy Markdown
Member Author

/deploy qa5

@tidebot

tidebot commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

clintonium-119 updated values.yaml file in qa5

@tidebot

tidebot commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

clintonium-119 updated flux policies file in qa5

@tidebot

tidebot commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

clintonium-119 deployed blip release-1.98.0 branch to qa5 namespace

@krystophv
krystophv requested a review from Copilot July 1, 2026 16:30
@krystophv

Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1d7ee754-b5a5-42a1-9fbc-ed4178b989ec

📥 Commits

Reviewing files that changed from the base of the PR and between 146fe89 and 1f9700d.

📒 Files selected for processing (1)
  • package.json
✅ Files skipped from review due to trivial changes (1)
  • package.json

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added a new donation-only data connection option, including provider-specific “connected” messaging and icons.
    • Enhanced the OAuth consent experience with an explicit approval step, privacy/consent details, and safer return-URL handling.
  • Bug Fixes

    • Kept the provider authorization popup open during the new approval step.
    • Improved consent checkbox auto-selection when the consent content fits without scrolling.
  • Documentation

    • Added project-wide agent/process guidelines.
  • Chores

    • Updated ignored files to exclude local agent artifacts and released version 1.98.0-rc.1.

Walkthrough

Adds Oura provider support and provider-specific connection states, introduces an OAuth accept step with guarded return handling, updates consent dialog read-state behavior, and refreshes related tests and project metadata.

Changes

Data Connections, OAuth Accept Flow, and Consent Dialog

Layer / File(s) Summary
Oura provider configuration and active-provider wiring
app/components/datasources/DataConnections.js
Adds the Oura provider entry, logo import, and default active-provider override.
Connection-state UI and eligibility logic
app/components/datasources/DataConnections.js
Updates provider-specific connected messaging, eligibility checks, handler lookup, logo selection, and rendered connection filtering.
OAuth popup accept-step handling
app/components/datasources/useProviderConnectionPopup.js, test/unit/components/useProviderConnectionPopup.test.js
Keeps the popup open on accept redirects and adds a test for that path.
OAuthConnection accept/consent UI
app/pages/oauth/OAuthConnection.js
Adds accept-flow state, consent content, safe return URL validation, guarded redirect handling, and revised auth-status rendering.
Consent dialog child/scroll logic
app/pages/patient/DataDonationConsentDialog.js
Adds child-based schema selection and auto-marks consent-read when the document fits without scrolling.
Banner copy update
app/providers/AppBanner/appBanners.js
Removes the refresh-page suffix from the data-source-connected banner text.
Test updates and mock fix
test/unit/components/chart/settings.test.js, test/unit/components/datasources/DataConnections.test.js, __tests__/unit/pages/dashboard/PatientDrawer/StackedDaily/StackedDaily.test.js
Updates Oura-related assertions, connection counts, popup coverage, and the datetime mock.
Version bump, gitignore, and agent guidelines
package.json, .gitignore, AGENTS.md
Bumps the package version, ignores .claude, and adds project-wide agent guidance.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant OAuthConnection
  participant useProviderConnectionPopup
  participant ProviderRedirect

  User->>OAuthConnection: Click "I understand"
  OAuthConnection->>OAuthConnection: handleAccept validates return_url
  OAuthConnection->>ProviderRedirect: window.location.href redirect
  useProviderConnectionPopup->>useProviderConnectionPopup: Detect accept status and keep popup open
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive No substantive description was provided, so its relevance cannot be assessed. Add a brief description of the release contents or major changes so reviewers can quickly understand the PR.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the release merge to master.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release-1.98.0

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the application and test suite for the 1.98.0 release line, introducing Oura as a donation-only OAuth data source with a new pre-authorization “accept” step and updating connection-state messaging/visibility rules for patients vs clinicians.

Changes:

  • Add Oura as an OAuth provider (donation-only) and adjust DataConnections filtering to hide certain providers for clinicians and/or when no existing data source exists.
  • Introduce an OAuth “accept” status page/flow and update popup-watching logic to not auto-close on /accept.
  • Update connected-state copy (e.g., “Awaiting data…”) and adjust/unit-test expectations accordingly.

Reviewed changes

Copilot reviewed 11 out of 17 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/unit/components/useProviderConnectionPopup.test.js Adds coverage for the new /accept pre-authorization behavior (popup should stay open, no toast).
test/unit/components/datasources/DataConnections.test.js Updates provider lists/UI expectations for Oura and new connected/awaiting messaging; adds visibility-rule tests.
test/unit/components/chart/settings.test.js Adjusts settings tests for clinician-visible providers (excluding requiresLoggedInUser providers like Oura).
package.json Bumps the package version for the release line.
app/providers/AppBanner/appBanners.js Updates “data source just connected” banner copy.
app/pages/patient/DataDonationConsentDialog.js Auto-marks consent step “read” when the consent content is not scrollable (portal timing-safe).
app/pages/oauth/OAuthConnection.js Adds accept-status UI/content, safe return_url validation, and accept redirect handling.
app/core/icons/oura_logo.svg Adds Oura logo asset (SVG).
app/core/icons/oura_logo_black.svg Adds Oura logo asset (black SVG).
app/components/datasources/useProviderConnectionPopup.js Avoids closing popup / triggering completion behavior on /accept intermediate step.
app/components/datasources/DataConnections.js Adds Oura provider configuration + donation-only connected messaging + provider filtering rules.
AGENTS.md Documents repo agent rules, restricted directories, and build/test conventions.
.gitignore Ignores .claude directory.
tests/unit/pages/dashboard/PatientDrawer/StackedDaily/StackedDaily.test.js Updates viz mocking shape for utils.datetime.getLocalizedCeiling.

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

Comment on lines 29 to +31
title: provider?.indeterminateDataImportTime
? t('If you have connected your {{displayName}} device, data is on its way. This usually takes a few minutes but occassionally takes longer. Refresh the page to see data.', provider)
: t('{{displayName}} data is on its way. This usually takes a few minutes but occasionally takes longer. Refresh the page to see data.', provider),
? t('If you have connected your {{displayName}} device, data is on its way. This usually takes a few minutes but occassionally takes longer.', provider)
: t('{{displayName}} data is on its way. This usually takes a few minutes but occasionally takes longer.', provider),
Comment on lines +122 to +129
// Validate return_url is a safe relative path to prevent open redirect attacks
if (isSafeReturnUrl(returnUrl)) {
window.location.href = returnUrl;
} else {
// eslint-disable-next-line no-console
console.error('OAuthConnection: invalid or missing return_url query parameter on accept.');
}
};
Comment on lines +168 to +170
<Flex sx={{ flexDirection: 'row', justifyContent: 'center' }} mb={5}>
<img src={logoSrc} width={190} />
</Flex>
Comment on lines +169 to +176
useEffect(() => {
if (!scrollContainer || !consentDocument?.content) return;
const fieldName = `${formSteps[currentConsentStep]}ConsentRead`;
if (formikContext.values[fieldName]) return;
if (scrollContainer.clientHeight > 0 && scrollContainer.scrollHeight <= scrollContainer.clientHeight) {
formikContext.setFieldValue(fieldName, true);
}
}, [scrollContainer, consentDocument?.content, currentConsentStep, formikContext.values]);
Comment thread package.json Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
app/pages/patient/DataDonationConsentDialog.js (1)

167-176: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Narrow the effect's dependency and include the setter function.

formikContext.values (the whole object) is used as a dependency, so the effect reruns on every unrelated field change (e.g. typing the caregiver name), not just when the relevant ConsentRead field changes — it's guarded from redundant writes but still wasteful. Also, formikContext.setFieldValue is used inside the effect but omitted from the dependency array.

♻️ Suggested refactor
   useEffect(() => {
     if (!scrollContainer || !consentDocument?.content) return;
     const fieldName = `${formSteps[currentConsentStep]}ConsentRead`;
-    if (formikContext.values[fieldName]) return;
+    if (formikContext.values[fieldName]) return;
     if (scrollContainer.clientHeight > 0 && scrollContainer.scrollHeight <= scrollContainer.clientHeight) {
       formikContext.setFieldValue(fieldName, true);
     }
-  }, [scrollContainer, consentDocument?.content, currentConsentStep, formikContext.values]);
+  }, [scrollContainer, consentDocument?.content, currentConsentStep, formikContext.values[`${formSteps[currentConsentStep]}ConsentRead`], formikContext.setFieldValue]);

As per coding guidelines, {app,__tests__,test,stories}/**/*.{js,jsx}: "Follow react-hooks/exhaustive-deps rules for hook dependencies."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/pages/patient/DataDonationConsentDialog.js` around lines 167 - 176, The
`useEffect` in `DataDonationConsentDialog` is depending on the entire
`formikContext.values` object, which makes it rerun on unrelated form updates;
change it to depend only on the specific `fieldName` value used by this effect.
Also include `formikContext.setFieldValue` in the dependency array since it is
referenced inside the effect. Keep the logic around `scrollContainer`,
`consentDocument?.content`, and `currentConsentStep` intact while tightening the
dependencies to satisfy `react-hooks/exhaustive-deps`.

Source: Coding guidelines

app/components/datasources/DataConnections.js (1)

336-354: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Minor: connectStateUI/inviteExpired are computed before the early-return checks.

getConnectStateUI(...) (which does time-ago formatting work) and inviteExpired are computed unconditionally at the top of the reducer callback, even for providers that get excluded a few lines later via the requiresLoggedInUser/requiresExistingDataSource early returns. Moving those two computations below the early-return guards would avoid the wasted work.

♻️ Optional reordering
   const provider = providers[providerName];
   const dataSource = getCurrentDataSourceForProvider(patient, providerName);
-  const connectStateUI = getConnectStateUI(patient, isLoggedInUser, providerName);
-  const inviteExpired = dataSource?.expirationTime < moment.utc().toISOString();

   // If the provider requires a logged in user to create the connection, then ensure that is the case.
   if (!!provider.requiresLoggedInUser && !isLoggedInUser) {
     return result;
   }

   // If the provider requires an existing data source to create the connection, then ensure that is the case.
   // This mechanism can be used to limit access to certain providers to only users who have previously connected
   // or where Tidepool has created a data source on their behalf.
   if (!!provider.requiresExistingDataSource && !dataSource) {
     return result;
   }

+  const connectStateUI = getConnectStateUI(patient, isLoggedInUser, providerName);
+  const inviteExpired = dataSource?.expirationTime < moment.utc().toISOString();
+
   let connectState;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/datasources/DataConnections.js` around lines 336 - 354, Move
the `getConnectStateUI(...)` and `inviteExpired` computations in
`DataConnections.js` so they run only after the `provider.requiresLoggedInUser`
and `provider.requiresExistingDataSource` early-return checks. Keep the existing
guard logic in the reducer callback, and compute those values only for providers
that actually continue past the exclusions to avoid unnecessary work.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 177-183: The markdown example fences in AGENTS.md are missing
language tags, which triggers markdownlint warnings. Update the example blocks
to use an explicit tag such as text so the fenced code samples are properly
labeled. Apply the same fix to the related example sections referenced by the
comment, keeping the formatting consistent across those blocks.

In `@app/pages/oauth/OAuthConnection.js`:
- Around line 225-232: The “I understand” button in OAuthConnection is reusing
the same DOM id as the mobile back button, which can confuse selectors. Update
the Button in the accept flow to use a distinct accept-specific id (for example,
one tied to the handleAccept action), and make sure the mobile “Back to
Tidepool” Button keeps its own separate id.
- Around line 167-171: The OAuthConnection logo render uses a raw img without
alt text, and it should match the theme-ui pattern used elsewhere in this
component. Update the isAcceptStatus block in OAuthConnection to use the
theme-ui Image component instead of img, and provide a meaningful explicit alt
attribute for the logo, keeping the existing logoSrc and sizing behavior intact.
- Around line 113-129: The handleAccept flow sets acceptProcessing to true
before validating return_url, so invalid or missing values leave the spinner
stuck. Move the loading state update in OAuthConnection.handleAccept so it only
happens on the safe redirect path, and make sure the invalid-return_url branch
resets or never sets the flag while surfacing an error to the user instead of
only logging to console.

---

Nitpick comments:
In `@app/components/datasources/DataConnections.js`:
- Around line 336-354: Move the `getConnectStateUI(...)` and `inviteExpired`
computations in `DataConnections.js` so they run only after the
`provider.requiresLoggedInUser` and `provider.requiresExistingDataSource`
early-return checks. Keep the existing guard logic in the reducer callback, and
compute those values only for providers that actually continue past the
exclusions to avoid unnecessary work.

In `@app/pages/patient/DataDonationConsentDialog.js`:
- Around line 167-176: The `useEffect` in `DataDonationConsentDialog` is
depending on the entire `formikContext.values` object, which makes it rerun on
unrelated form updates; change it to depend only on the specific `fieldName`
value used by this effect. Also include `formikContext.setFieldValue` in the
dependency array since it is referenced inside the effect. Keep the logic around
`scrollContainer`, `consentDocument?.content`, and `currentConsentStep` intact
while tightening the dependencies to satisfy `react-hooks/exhaustive-deps`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 73430153-0b7a-43d1-8cb2-5b0644d3a291

📥 Commits

Reviewing files that changed from the base of the PR and between 97eabb4 and 146fe89.

⛔ Files ignored due to path filters (5)
  • app/core/icons/oura_logo.png is excluded by !**/*.png
  • app/core/icons/oura_logo.svg is excluded by !**/*.svg
  • app/core/icons/oura_logo_black.png is excluded by !**/*.png
  • app/core/icons/oura_logo_black.svg is excluded by !**/*.svg
  • app/pages/oauth/images/consent_data.png is excluded by !**/*.png
📒 Files selected for processing (12)
  • .gitignore
  • AGENTS.md
  • __tests__/unit/pages/dashboard/PatientDrawer/StackedDaily/StackedDaily.test.js
  • app/components/datasources/DataConnections.js
  • app/components/datasources/useProviderConnectionPopup.js
  • app/pages/oauth/OAuthConnection.js
  • app/pages/patient/DataDonationConsentDialog.js
  • app/providers/AppBanner/appBanners.js
  • package.json
  • test/unit/components/chart/settings.test.js
  • test/unit/components/datasources/DataConnections.test.js
  • test/unit/components/useProviderConnectionPopup.test.js

Comment thread AGENTS.md
Comment on lines +177 to +183
```
<Imperative summary (50 chars or less)>

<Optional body: 2-4 sentences>

<Optional bullet points, one per line with "- ">
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add language tags to the example code fences.

These unlabeled fences trigger the markdownlint warning and should be tagged explicitly (for example, text).

🛠 Suggested fix
-```
+```text

Also applies to: 192-201, 203-211

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 177-177: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` around lines 177 - 183, The markdown example fences in AGENTS.md
are missing language tags, which triggers markdownlint warnings. Update the
example blocks to use an explicit tag such as text so the fenced code samples
are properly labeled. Apply the same fix to the related example sections
referenced by the comment, keeping the formatting consistent across those
blocks.

Source: Linters/SAST tools

Comment on lines +113 to +129
const handleAccept = () => {
// Return to the authorization flow after accepting. The backend may enforce (or not) any
// actual acceptance requirements for the connection (e.g. formal consent) and, if not met,
// reroute back to this accept step until resolved. In the basic case, the backend does not
// impose actual acceptance requirements other than just adding the accepted query param.
trackMetric('Oauth - Connection - Accept', { providerName, status });
setAcceptProcessing(true);
const returnUrl = queryParams.get('return_url');

// Validate return_url is a safe relative path to prevent open redirect attacks
if (isSafeReturnUrl(returnUrl)) {
window.location.href = returnUrl;
} else {
// eslint-disable-next-line no-console
console.error('OAuthConnection: invalid or missing return_url query parameter on accept.');
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

acceptProcessing is never reset when return_url is invalid/missing.

setAcceptProcessing(true) runs before validation, so when isSafeReturnUrl fails the button remains in the processing/spinner state indefinitely with only a console.error and no user-facing feedback. Set the flag only on the successful redirect path (and surface an error otherwise).

🛠️ Proposed fix
   const handleAccept = () => {
     trackMetric('Oauth - Connection - Accept', { providerName, status });
-    setAcceptProcessing(true);
     const returnUrl = queryParams.get('return_url');

     // Validate return_url is a safe relative path to prevent open redirect attacks
     if (isSafeReturnUrl(returnUrl)) {
+      setAcceptProcessing(true);
       window.location.href = returnUrl;
     } else {
       // eslint-disable-next-line no-console
       console.error('OAuthConnection: invalid or missing return_url query parameter on accept.');
     }
   };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleAccept = () => {
// Return to the authorization flow after accepting. The backend may enforce (or not) any
// actual acceptance requirements for the connection (e.g. formal consent) and, if not met,
// reroute back to this accept step until resolved. In the basic case, the backend does not
// impose actual acceptance requirements other than just adding the accepted query param.
trackMetric('Oauth - Connection - Accept', { providerName, status });
setAcceptProcessing(true);
const returnUrl = queryParams.get('return_url');
// Validate return_url is a safe relative path to prevent open redirect attacks
if (isSafeReturnUrl(returnUrl)) {
window.location.href = returnUrl;
} else {
// eslint-disable-next-line no-console
console.error('OAuthConnection: invalid or missing return_url query parameter on accept.');
}
};
const handleAccept = () => {
// Return to the authorization flow after accepting. The backend may enforce (or not) any
// actual acceptance requirements for the connection (e.g. formal consent) and, if not met,
// reroute back to this accept step until resolved. In the basic case, the backend does not
// impose actual acceptance requirements other than just adding the accepted query param.
trackMetric('Oauth - Connection - Accept', { providerName, status });
const returnUrl = queryParams.get('return_url');
// Validate return_url is a safe relative path to prevent open redirect attacks
if (isSafeReturnUrl(returnUrl)) {
setAcceptProcessing(true);
window.location.href = returnUrl;
} else {
// eslint-disable-next-line no-console
console.error('OAuthConnection: invalid or missing return_url query parameter on accept.');
}
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/pages/oauth/OAuthConnection.js` around lines 113 - 129, The handleAccept
flow sets acceptProcessing to true before validating return_url, so invalid or
missing values leave the spinner stuck. Move the loading state update in
OAuthConnection.handleAccept so it only happens on the safe redirect path, and
make sure the invalid-return_url branch resets or never sets the flag while
surfacing an error to the user instead of only logging to console.

Comment on lines +167 to +171
{isAcceptStatus && (
<Flex sx={{ flexDirection: 'row', justifyContent: 'center' }} mb={5}>
<img src={logoSrc} width={190} />
</Flex>
)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use theme-ui Image and add an alt attribute for the logo.

This raw <img> has no alt (jsx-a11y/alt-text) and is inconsistent with the theme-ui Image used at Line 192. Use Image with an explicit alt.

♻️ Proposed change
-            <img src={logoSrc} width={190} />
+            <Image src={logoSrc} alt="Tidepool" sx={{ width: '190px' }} />

As per coding guidelines: "Use theme-ui components such as Box, Flex, Text, Divider, and Link for layout and styling."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{isAcceptStatus && (
<Flex sx={{ flexDirection: 'row', justifyContent: 'center' }} mb={5}>
<img src={logoSrc} width={190} />
</Flex>
)}
{isAcceptStatus && (
<Flex sx={{ flexDirection: 'row', justifyContent: 'center' }} mb={5}>
<Image src={logoSrc} alt="Tidepool" sx={{ width: '190px' }} />
</Flex>
)}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/pages/oauth/OAuthConnection.js` around lines 167 - 171, The
OAuthConnection logo render uses a raw img without alt text, and it should match
the theme-ui pattern used elsewhere in this component. Update the isAcceptStatus
block in OAuthConnection to use the theme-ui Image component instead of img, and
provide a meaningful explicit alt attribute for the logo, keeping the existing
logoSrc and sizing behavior intact.

Source: Coding guidelines

Comment on lines +225 to +232
<Button
id="oauth-redirect-home-button"
variant="primary"
onClick={handleAccept}
processing={acceptProcessing}
>
{t('I understand')}
</Button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Duplicate DOM id oauth-redirect-home-button.

This accept "I understand" button reuses the same id as the mobile "Back to Tidepool" button (Line 271). They're mutually exclusive at render time, but the shared id is misleading and can collide with id-based test/metric selectors. Rename to something accept-specific (e.g. oauth-accept-button).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/pages/oauth/OAuthConnection.js` around lines 225 - 232, The “I
understand” button in OAuthConnection is reusing the same DOM id as the mobile
back button, which can confuse selectors. Update the Button in the accept flow
to use a distinct accept-specific id (for example, one tied to the handleAccept
action), and make sure the mobile “Back to Tidepool” Button keeps its own
separate id.

@krystophv
krystophv merged commit 74ec64c into master Jul 2, 2026
6 checks passed
@clintonium-119
clintonium-119 deleted the release-1.98.0 branch July 2, 2026 13:09
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.

5 participants