Skip to content

[NoQA] Chore: Add cert info to Sentry logs - #105248

Merged
mjasikowski merged 5 commits into
Expensify:mainfrom
software-mansion-labs:cert-pinning-ios-chain-diagnostics
Nov 6, 2026
Merged

mjasikowski merged 5 commits into
Expensify:mainfrom
software-mansion-labs:cert-pinning-ios-chain-diagnostics

Conversation

@staszekscp

@staszekscp staszekscp commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

Adds information to Sentry logs to understand Certificate Pinning warnings before going live

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/633469
$ https://github.com/Expensify/Expensify/issues/682201
PROPOSAL:

Tests

Offline tests

QA Steps

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified any copy / text that was added to the app is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This PR is possibly changing native code and/or updating libraries, it may cause problems with HybridApp. Please check if any patch updates are required in the HybridApp repo and run an AdHoc build to verify that HybridApp will not break. Ask Contributor Plus for help if you are not sure how to handle this. ⚠️

@staszekscp staszekscp changed the title Chore: Add cert info to Sentry logs [NoQA] Chore: Add cert info to Sentry logs Oct 29, 2026
@staszekscp
staszekscp marked this pull request as ready for review October 29, 2026 11:13
@staszekscp
staszekscp requested a review from a team as a code owner October 29, 2026 11:13
@melvin-bot
melvin-bot Bot requested a review from eVoloshchak October 29, 2026 11:13
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-11-03T10:44:41.855695Z
We couldn’t complete this review. Comment @codex review to try again.
57ad865 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@melvin-bot
melvin-bot Bot removed the request for review from a team October 29, 2026 11:13
@melvin-bot

melvin-bot Bot commented Oct 29, 2026

Copy link
Copy Markdown

@eVoloshchak Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@staszekscp

Copy link
Copy Markdown
Contributor Author

@eVoloshchak @mjasikowski Hey! May I ask for review, so we can move forward? 😄

@mjasikowski
mjasikowski self-requested a review November 2, 2026 10:40
Comment thread ios/CertificatePinning.swift Outdated
Comment on lines +33 to +35
/// Identifies the pin list a client shipped with, independent of the app version: the `_lastGenerated`
/// value of config/certificatePinning/pins.json these hashes were copied from. Update it together with
/// the hashes. Reported as `certificate_pinning_pin_set_version`.

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.

Suggested change
/// Identifies the pin list a client shipped with, independent of the app version: the `_lastGenerated`
/// value of config/certificatePinning/pins.json these hashes were copied from. Update it together with
/// the hashes. Reported as `certificate_pinning_pin_set_version`.
/// Identifies the shipped pin set independently of the app version using `_lastGenerated`
/// from config/certificatePinning/pins.json. Update it with the hashes.
/// Reported as `certificate_pinning_pin_set_version`.

Comment thread ios/CertificatePinning.swift Outdated
Comment on lines +128 to +139
// MARK: - Reporting
//
// TrustKit only says *that* a pin did not match; the attributes below record *what* iOS validated
// (the full chain, the trust anchor, how the device trusts that anchor, and the network context) so
// a mismatch in Sentry can be classified as a CA we do not pin versus a TLS-intercepting proxy
// without a device in hand. Keep this set in sync with Mobile-Expensify's
// iOS/Expensify/CertificatePinningReporter.m and the table in config/certificatePinning/README.md.
//
// Sentry's attribute converter matches Bool before Int, so any number holding 0 or 1 lands as a
// boolean and the column type flaps between releases. Enum values are therefore strings, counts
// that can be 0 or 1 are strings, real flags are Bool, and the validation duration is reported in
// microseconds (never 0 or 1 in practice).

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.

Suggested change
// MARK: - Reporting
//
// TrustKit only says *that* a pin did not match; the attributes below record *what* iOS validated
// (the full chain, the trust anchor, how the device trusts that anchor, and the network context) so
// a mismatch in Sentry can be classified as a CA we do not pin versus a TLS-intercepting proxy
// without a device in hand. Keep this set in sync with Mobile-Expensify's
// iOS/Expensify/CertificatePinningReporter.m and the table in config/certificatePinning/README.md.
//
// Sentry's attribute converter matches Bool before Int, so any number holding 0 or 1 lands as a
// boolean and the column type flaps between releases. Enum values are therefore strings, counts
// that can be 0 or 1 are strings, real flags are Bool, and the validation duration is reported in
// microseconds (never 0 or 1 in practice).
// MARK: - Reporting
//
// Record TrustKit's certificate chain, a fresh system trust result, and network settings
// to help investigate pin failures in Sentry. These fields help distinguish an unpinned
// CA from a proxy, but do not establish the cause on their own.
// Keep these fields in sync with Mobile-Expensify's iOS/Expensify/CertificatePinningReporter.m
// and the field descriptions in config/certificatePinning/README.md.
//
// In attributes, enum names and counts are strings, flags are Bool, and validation
// duration is an integer number of microseconds. Send fields listed in extraKeys as
// extras and convert all other values to strings for tags.

Comment thread ios/CertificatePinning.swift Outdated
} else if path.usesInterfaceType(.wiredEthernet) {
currentInterfaceType = "wired"
} else if path.usesInterfaceType(.other) {
currentInterfaceType = "other" // VPN or tunnel

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.

Suggested change
currentInterfaceType = "other" // VPN or tunnel
currentInterfaceType = "other" // Virtual or otherwise unknown interface

Comment thread ios/CertificatePinning.swift Outdated
occurrenceCounts[dedupKey] = occurrence

var attributes: [String: Any] = [
// Existing attributes, unchanged

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.

Suggested change
// Existing attributes, unchanged

Comment thread ios/CertificatePinning.swift Outdated
// Existing attributes, unchanged
certificatePinningHostTag: hostname,
certificatePinningModeTag: enforcePinning ? "enforce" : "monitor",
// Typed replacement for the old numeric `certificate_pinning_evaluation_result`

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.

Suggested change
// Typed replacement for the old numeric `certificate_pinning_evaluation_result`
// TrustKit's evaluation result and connection decision, plus the system trust result

Comment thread ios/CertificatePinning.swift Outdated
Comment on lines +211 to +212
// One captured error per failed validation in both modes, exactly as before; the detail above
// rides along as tags and extras.

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.

Suggested change
// One captured error per failed validation in both modes, exactly as before; the detail above
// rides along as tags and extras.
// Capture one error for each failed validation in either mode, with these attributes
// attached as tags and extras.

Comment thread ios/CertificatePinning.swift Outdated
Comment on lines +252 to +254
/// `proceed` means the anchor is explicitly trusted by the user or an MDM profile ("Enable Full Trust for
/// Root Certificates"); `unspecified` means a system root with no user override. This is the cheapest
/// single signal separating a TLS-intercepting proxy from a public CA we do not pin.

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.

Suggested change
/// `proceed` means the anchor is explicitly trusted by the user or an MDM profile ("Enable Full Trust for
/// Root Certificates"); `unspecified` means a system root with no user override. This is the cheapest
/// single signal separating a TLS-intercepting proxy from a public CA we do not pin.
/// `proceed` indicates a successful evaluation based on a user trust decision;
/// `unspecified` indicates success without an explicit user decision.
/// Neither result alone identifies a proxy or proves the anchor is a public CA.

Comment thread ios/CertificatePinning.swift Outdated
Comment on lines +311 to +315
/// Re-runs the system trust evaluation on the chain TrustKit validated. TrustKit 3.x does not expose the
/// original SecTrust, so this is the only way to learn how the device classified the anchor
/// (`SecTrustResultType`) and, for an untrusted chain, why ("expired", "not trusted", hostname mismatch...).
/// Revocation checking is best-effort and may touch the network, which is why this never runs on the
/// main queue.

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.

Suggested change
/// Re-runs the system trust evaluation on the chain TrustKit validated. TrustKit 3.x does not expose the
/// original SecTrust, so this is the only way to learn how the device classified the anchor
/// (`SecTrustResultType`) and, for an untrusted chain, why ("expired", "not trusted", hostname mismatch...).
/// Revocation checking is best-effort and may touch the network, which is why this never runs on the
/// main queue.
/// Evaluates TrustKit's certificate chain with an SSL policy for hostname.
/// Returns the new evaluation's SecTrustResultType and any error messages.
/// TrustKit does not expose its original SecTrust in the callback, so this evaluation
/// may differ from the original. It runs on reportingQueue because trust evaluation
/// can block while fetching certificates or checking revocation.

Comment thread ios/CertificatePinning.swift Outdated
Comment on lines +351 to +353
/// Presence only: never the proxy host or PAC URL, which would identify the customer's network. Per-interface
/// settings under `__SCOPED__` reveal tunnels (utun/ipsec/ppp/tap), which is where per-app VPN and TLS
/// inspection usually live.

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.

Suggested change
/// Presence only: never the proxy host or PAC URL, which would identify the customer's network. Per-interface
/// settings under `__SCOPED__` reveal tunnels (utun/ipsec/ppp/tap), which is where per-app VPN and TLS
/// inspection usually live.
/// Reports whether HTTP proxy and PAC settings are enabled, and whether `__SCOPED__`
/// contains an interface whose name starts with utun, tun, tap, ppp, or ipsec.
/// These names suggest a tunnel but do not prove this connection uses a VPN.
/// The proxy host and PAC URL are omitted to protect network details.

Comment on lines +29 to +35
/**
* The HybridApp pin lists live in the Mobile-Expensify submodule and are what actually ships to the stores.
* They drifted from pins.json once already (the Sectigo roots were missing for a month and every HybridApp
* build reported the 2026-10 Sectigo chain on staging.expensify.com as a mismatch), so they are checked
* here too whenever the submodule is checked out. CI for this suite does not fetch the submodule, so that
* check only runs locally and in HybridApp builds; a missing submodule is skipped rather than failed.
*/

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.

Suggested change
/**
* The HybridApp pin lists live in the Mobile-Expensify submodule and are what actually ships to the stores.
* They drifted from pins.json once already (the Sectigo roots were missing for a month and every HybridApp
* build reported the 2026-10 Sectigo chain on staging.expensify.com as a mismatch), so they are checked
* here too whenever the submodule is checked out. CI for this suite does not fetch the submodule, so that
* check only runs locally and in HybridApp builds; a missing submodule is skipped rather than failed.
*/
/**
* Keep the HybridApp pin lists used in store builds in sync with pins.json.
* Include each Mobile-Expensify file that exists when this suite runs.
* Missing files are skipped so the suite can run without the submodule.
*/

@staszekscp

Copy link
Copy Markdown
Contributor Author

Thanks for the review @mjasikowski, I've applied the changes! Can I also ask for review in this PR so we have the full package? 😄

@mjasikowski

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Failed to set up container
ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@mjasikowski

mjasikowski commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

@codex review
you donkey

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Failed to set up container
ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@mjasikowski

Copy link
Copy Markdown
Contributor

@MelvinBot review

@MelvinBot

Copy link
Copy Markdown
Contributor

Review

The diagnostics design looks good. Threading is safe: all shared state is touched only on the serial reportingQueue, and TrustKit 3.0.7 supports pinningValidatorCallbackQueue. I found one bug and two items to check before merge.

1. The first report in each session always has certificate_pinning_interface: unknown — ios/CertificatePinning.swift:151-166
The NWPathMonitor starts lazily inside reportPinningFailure, which already runs on reportingQueue. Its first pathUpdateHandler call is queued behind the running report, so interfaceType() returns the default value. The first report is usually the one that matters most.
Fix: start the monitor eagerly by adding _ = pathMonitor in initialize() right after TrustKit.initSharedInstance.

2. Check the Sentry tag limits — ios/CertificatePinning.swift:205-220

  • certificate_pinning_trust_errors can easily go over the 200-character tag value limit, because it joins several system error strings. Add it to extraKeys.
  • Sentry documents a 32-character limit for tag keys. 11 of the new keys are longer, for example certificate_pinning_vpn_interface_present (43) and certificate_pinning_validation_duration_us (42). I couldn't confirm whether current Relay drops them. Before you rely on them, check one release-build event on staging.
  • Optional: send the full set as one scope.setContext(value:key: "certificate_pinning") dictionary. Keep only a few short keys as tags for searching, such as host, mode, result and sec_trust_result. Contexts have neither limit and keep Bool/Int types. Tags stringify everything, so the README's "typed" note only applies to the HybridApp log path.

3. CI never runs the new HybridApp sync checks — tests/unit/generateCertificatePinsTest.ts:34-38
test.yml doesn't check out the Mobile-Expensify submodule, so hybridAppPinFiles is always empty in CI. The check runs only on machines that have the submodule. On those machines it can fail for two reasons:

  • The submodule is at an older commit than the pins.
  • BASE64_SHA256_REGEX matches an unrelated 44-character base64 string in a large file like ExpensifyAppDelegate.m. Then the unknownHashes assertion fails.

Please confirm the test passes locally with the submodule at the commit this PR pins.


view run

@mjasikowski

Copy link
Copy Markdown
Contributor

@staszekscp mind checking validity of Melvin's claims?

@mjasikowski
mjasikowski self-requested a review November 6, 2026 09:56
mjasikowski
mjasikowski previously approved these changes Nov 6, 2026
@mjasikowski mjasikowski closed this Nov 6, 2026
@mjasikowski mjasikowski reopened this Nov 6, 2026
@mjasikowski

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
Android: mWeb Chrome
iOS: HybridApp
iOS: mWeb Safari
MacOS: Chrome / Safari

@mjasikowski
mjasikowski merged commit 7d1ce04 into Expensify:main Nov 6, 2026
39 of 41 checks passed
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

🚧 mjasikowski has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

OSBotify commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

@OSBotify OSBotify mentioned this pull request Nov 7, 2026
85 tasks done
@OSBotify

OSBotify commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/mjasikowski in version: 9.5.34-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify

OSBotify commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/yuwenmemon in version: 9.5.34-1 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

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.

4 participants