Skip to content

feat(auth): Refuse addPlugin from a secondary isolate without a messenger (#5302) - #7272

Draft
cadivus wants to merge 1 commit into
feat/isolate-guard-datastorefrom
feat/isolate-guard-auth
Draft

feat(auth): Refuse addPlugin from a secondary isolate without a messenger (#5302)#7272
cadivus wants to merge 1 commit into
feat/isolate-guard-datastorefrom
feat/isolate-guard-auth

Conversation

@cadivus

@cadivus cadivus commented Aug 12, 2026

Copy link
Copy Markdown
Member

Second per-category guardrail for #5302, stacked on #7271.

  • AmplifyAuthCognito.addPlugin now throws a PluginError naming the cause instead of letting a bare StateError escape from inside Pigeon. Gated on messenger availability, not root-isolate identity: a headless FlutterEngine always has a messenger, so the guard provably cannot fire in amplifyBackgroundProcessing — which adds this very plugin from such an engine. The broader check would have rested on an unverified claim, and being wrong there breaks push handling in shipped apps.
  • No duplicated predicate — amplify_auth_cognito already depends on amplify_flutter, so it imports the canonical @internal getter. Duplication stays at n=1 (amplify_datastore only).
  • Known gap, documented in code and pinned by a test: a secondary isolate already bootstrapped with a messenger passes the guard. It still cannot work — Flutter itself refuses with UnsupportedError: Background isolates do not support setMessageHandler(). Messages from the host platform always go to the root isolate. Host-to-Dart callbacks are impossible off the root isolate, which bounds what Isolate Support #5302 can ever support.
  • 3 new tests, all in CI (fires without a messenger; does not fire on root; does not fire when bootstrapped). Full amplify_auth_cognito suite green.

Follow-up not in this stack: the push guard is deferred — it needs an integration_test/ harness, an e2e_android leg, and a test-only native hook to invoke the background service and report the predicate. Native work with its own testing plan.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 41.08%. Comparing base (1f11e54) to head (eb72956).

Additional details and impacted files
@@                       Coverage Diff                        @@
##           feat/isolate-guard-datastore    #7272      +/-   ##
================================================================
+ Coverage                         32.68%   41.08%   +8.40%     
================================================================
  Files                                34      126      +92     
  Lines                              2374     8331    +5957     
  Branches                            915     3632    +2717     
================================================================
+ Hits                                776     3423    +2647     
- Misses                             1598     4908    +3310     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…nger (#5302)

Second of the per-category #5302 guardrails. `AmplifyAuthCognito.addPlugin`
registers with the process-wide native Cognito SDK, starting with
`NativeAuthPlugin.setUp`. Without a guard a secondary isolate got a bare
`StateError` about `BackgroundIsolateBinaryMessenger` from inside Pigeon, which
says nothing about Amplify, Auth or isolates.

Gated on messenger availability rather than root-isolate identity. A headless
`FlutterEngine` always has a working messenger, so the guard provably cannot
fire there -- which matters because `amplifyBackgroundProcessing` adds this very
plugin from such an engine. The broader root-token check would have rested on an
unverified claim about headless engines, and the cost of being wrong is broken
push handling in shipped apps.

No duplicated predicate: amplify_auth_cognito already depends on
amplify_flutter, so it imports the canonical `@internal` getter directly.

Documents, in code and in an executable test, that this does not catch a
secondary isolate which has already been bootstrapped with a messenger. That
case cannot work regardless: Flutter itself refuses it with `UnsupportedError:
Background isolates do not support setMessageHandler(). Messages from the host
platform always go to the root isolate.` Host-to-Dart callbacks are impossible
off the root isolate, which bounds what #5302 can ever support.
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