Skip to content

feat(telemetry): add Firebase auth consensus - #1306

Merged
benceruleanlu merged 2 commits into
mainfrom
bl/gtm-93-e-firebase-auth-consensus
Jul 29, 2026
Merged

feat(telemetry): add Firebase auth consensus#1306
benceruleanlu merged 2 commits into
mainfrom
bl/gtm-93-e-firebase-auth-consensus

Conversation

@benceruleanlu

@benceruleanlu benceruleanlu commented Jul 24, 2026

Copy link
Copy Markdown
Member

Split E of #1249.

Summary

  • Add frame-bound Firebase auth consensus across trusted Cloud, Desktop-verified loopback, and fail-closed remote fallback reporters.
  • Replace renderer bind/unbind IPC with declarative auth-state reporting.
  • Persist verified loopback authorization and monitor local Firebase IndexedDB from preload.
  • Route the desktop login-code seam through the process-wide consensus and publish bridge types 0.1.3.
  • Fail closed across identity replacement, logout, navigation/frame races, detached hosts, persistence failures, and canceled loads.

This final slice depends functionally on B and C; D is included because the GitHub stack is linear.

Stack

Split PR Base Release gate
A #1302 — download-path extraction main Normal
B #1303 — desktop login-code auth A Packaged RC
C #1304 — anonymous identity core B Normal
D #1305 — installer website-ID carrier C Packaged Windows RC
E #1306 — Firebase auth consensus D Packaged RC

Validation

  • pnpm run typecheck
  • pnpm run lint
  • pnpm run build
  • pnpm run test — 3,078 passed, 1 skipped
  • Focused identity/IPC/preload suite — 211 passed
  • Independent security/lifecycle review: no remaining actionable findings

RC gate

Validate packaged multi-window login/logout/account-switch behavior, Cloud and local/remote installs, navigation/frame replacement, and identity recovery before rollout.

@coderabbitai

coderabbitai Bot commented Jul 24, 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: ASSERTIVE

Plan: Pro Plus

Run ID: 31e196f6-ef4b-4c14-bbc6-07cb455d0019

📥 Commits

Reviewing files that changed from the base of the PR and between 64c8a44 and 36f2124.

📒 Files selected for processing (1)
  • src/main/lib/firebaseAuthIdentity.ts

📝 Walkthrough

Walkthrough

The PR adds Firebase auth-state reporting and process-wide consensus across hosted and loopback views. It introduces auth contracts, IndexedDB monitoring, trusted persistence, navigation-aware reconciliation, validated IPC, anonymous epoch handling, lifecycle wiring, and tests.

Changes

Firebase auth identity consensus

Layer / File(s) Summary
Auth contracts and trust primitives
packages/comfyui-desktop-bridge-types/..., src/types/comfyDesktopBridge.ts, src/main/lib/opaqueIdentifier.ts, src/main/lib/trustedCloudUrl.ts, src/main/lib/verifiedLocalFirebaseAuth.ts, src/main/lib/anonymousIdentity.ts, src/main/lib/*test.ts
Adds Firebase auth-state contracts, trusted-origin checks, illegal distinct-ID validation, loopback user persistence, and durable anonymous epoch markers.
Preload auth monitoring and bridge wiring
src/preload/localFirebaseAuthMonitor.ts, src/preload/comfyPreload.ts, src/preload/api.ts, src/types/ipc.ts, src/renderer/src/lib/rendererBootstrap.ts, src/preload/*test.ts
Reads Firebase state from IndexedDB on loopback pages, reports changes through telemetry, and removes legacy bind/unbind bridge methods.
Process-wide consensus and lifecycle integration
src/main/lib/firebaseAuthIdentity.ts, src/main/lib/telemetry.ts, src/main/auth/firebaseBridge/flowShared.ts, src/main/host/*, src/main/lib/*test.ts
Tracks reporter navigation and frame identity, reconciles auth states, handles conflicts and anonymous epochs, and wires consensus into Firebase flows and host lifecycle.
Validated Firebase auth IPC
src/main/lib/ipc/registerTelemetryHandlers.ts, src/main/lib/ipc/registerTelemetryHandlers.test.ts
Replaces bind/unbind handlers with main-frame and payload validation before forwarding Firebase auth states to the consensus coordinator.

Sequence Diagram(s)

sequenceDiagram
  participant LocalFirebaseAuthMonitor
  participant ComfyPreload
  participant registerTelemetryHandlers
  participant firebaseAuthIdentity
  participant telemetry
  LocalFirebaseAuthMonitor->>ComfyPreload: emit Firebase auth state
  ComfyPreload->>registerTelemetryHandlers: send telemetry:firebaseAuthState
  registerTelemetryHandlers->>firebaseAuthIdentity: validate and report frame/state
  firebaseAuthIdentity->>firebaseAuthIdentity: reconcile active reporters
  firebaseAuthIdentity->>telemetry: apply consensus identity
Loading

Possibly related PRs

Suggested reviewers: kosinkadink, deepme987, maanilverma

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
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 bl/gtm-93-e-firebase-auth-consensus
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch bl/gtm-93-e-firebase-auth-consensus

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@benceruleanlu
benceruleanlu force-pushed the bl/gtm-93-d-installer-website-id branch from d0d4bdc to 924bdbf Compare July 29, 2026 18:59
Base automatically changed from bl/gtm-93-d-installer-website-id to main July 29, 2026 20:32
@benceruleanlu
benceruleanlu force-pushed the bl/gtm-93-e-firebase-auth-consensus branch 2 times, most recently from 1e92d01 to 595e946 Compare July 29, 2026 20:58
@benceruleanlu
benceruleanlu force-pushed the bl/gtm-93-e-firebase-auth-consensus branch from 595e946 to 64c8a44 Compare July 29, 2026 21:36
@benceruleanlu
benceruleanlu marked this pull request as ready for review July 29, 2026 21:37

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/auth/firebaseBridge/flowShared.ts (1)

64-77: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard stale bindings before dereferencing source.

Current call sites pass comfyContents from live flows, but the helper should still reject undefined/destroyed WebContents before source.getURL()—otherwise the quiet catch becomes a no-hop, no-bind dead end.

🤖 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 `@src/main/auth/firebaseBridge/flowShared.ts` around lines 64 - 77, Update
bindSignedInUser to validate source before invoking bindMainVerifiedFirebaseUser
or any source-dependent operation: reject undefined or destroyed WebContents,
while preserving the existing UID and property-building flow for valid sources.
Ensure stale sources exit safely rather than relying on the catch block.
🤖 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 `@src/main/lib/anonymousIdentity.test.ts`:
- Around line 85-94: The test should verify that the unmergeable epoch marker
survives rotatePersistedAnonymousDistinctId(). Add an assertion immediately
after the rotation confirming hasPersistedUnmergeableAnonymousEpoch() is true,
while preserving the existing assertion that
clearPersistedUnmergeableAnonymousEpoch() removes it.

In `@src/main/lib/firebaseAuthIdentity.test.ts`:
- Around line 34-38: Add a verifiedLocalRevocation.succeeds toggle to the
firebaseAuthIdentity test mock, mirroring verifiedLocalPersistence, and make
clearVerifiedLocalFirebaseUser return failure without deleting the user when the
toggle is false. Add a test covering failed revocation and assert the identity
is not re-bound afterward, exercising the fail-closed behavior in
firebaseAuthIdentity.

In `@src/main/lib/firebaseAuthIdentity.ts`:
- Around line 105-122: Update revokeAcceptedLocalAuthorization to inspect the
boolean result from clearVerifiedLocalFirebaseUser. When persistence fails,
retain a fail-closed pending/unmergeable state that prevents
refreshReporterAuthScope and subsequent restarts from restoring
localReportingAuthorized or including the reporter in consensus until revocation
succeeds.

---

Outside diff comments:
In `@src/main/auth/firebaseBridge/flowShared.ts`:
- Around line 64-77: Update bindSignedInUser to validate source before invoking
bindMainVerifiedFirebaseUser or any source-dependent operation: reject undefined
or destroyed WebContents, while preserving the existing UID and
property-building flow for valid sources. Ensure stale sources exit safely
rather than relying on the catch block.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: 1c405d38-dc03-4b39-88ee-8a4fafce43a2

📥 Commits

Reviewing files that changed from the base of the PR and between b6ccfc4 and 64c8a44.

📒 Files selected for processing (26)
  • packages/comfyui-desktop-bridge-types/comfyDesktopBridge.d.ts
  • packages/comfyui-desktop-bridge-types/package.json
  • src/main/auth/firebaseBridge/flowShared.ts
  • src/main/host/attach.ts
  • src/main/host/createHostWindow.ts
  • src/main/lib/anonymousIdentity.test.ts
  • src/main/lib/anonymousIdentity.ts
  • src/main/lib/firebaseAuthIdentity.test.ts
  • src/main/lib/firebaseAuthIdentity.ts
  • src/main/lib/ipc/registerTelemetryHandlers.test.ts
  • src/main/lib/ipc/registerTelemetryHandlers.ts
  • src/main/lib/opaqueIdentifier.test.ts
  • src/main/lib/opaqueIdentifier.ts
  • src/main/lib/telemetry.test.ts
  • src/main/lib/telemetry.ts
  • src/main/lib/trustedCloudUrl.test.ts
  • src/main/lib/trustedCloudUrl.ts
  • src/main/lib/verifiedLocalFirebaseAuth.test.ts
  • src/main/lib/verifiedLocalFirebaseAuth.ts
  • src/preload/api.ts
  • src/preload/comfyPreload.ts
  • src/preload/localFirebaseAuthMonitor.test.ts
  • src/preload/localFirebaseAuthMonitor.ts
  • src/renderer/src/lib/rendererBootstrap.ts
  • src/types/comfyDesktopBridge.ts
  • src/types/ipc.ts
💤 Files with no reviewable changes (2)
  • src/preload/api.ts
  • src/types/ipc.ts

Comment on lines +85 to +94
it('persists an unmergeable epoch across restarts until a clean rotation clears it', () => {
expect(persistAnonymousDistinctId(ANONYMOUS_ID_1)).toBe(true)
expect(persistUnmergeableAnonymousEpoch()).toBe(true)

expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(true)
expect(readPersistedAnonymousDistinctId()).toBe(ANONYMOUS_ID_1)
expect(rotatePersistedAnonymousDistinctId()).not.toBeNull()
expect(clearPersistedUnmergeableAnonymousEpoch()).toBe(true)
expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(false)
})

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 | 🔵 Trivial | ⚡ Quick win

Assert the marker survives the rotation the title promises.

The name says the epoch persists "until a clean rotation clears it", but nothing checks the marker is still set after rotatePersistedAnonymousDistinctId() — so a regression where rotation silently wipes the taint would slip past unnoticed.

🧪 Proposed assertion
     expect(rotatePersistedAnonymousDistinctId()).not.toBeNull()
+    expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(true)
     expect(clearPersistedUnmergeableAnonymousEpoch()).toBe(true)
📝 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
it('persists an unmergeable epoch across restarts until a clean rotation clears it', () => {
expect(persistAnonymousDistinctId(ANONYMOUS_ID_1)).toBe(true)
expect(persistUnmergeableAnonymousEpoch()).toBe(true)
expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(true)
expect(readPersistedAnonymousDistinctId()).toBe(ANONYMOUS_ID_1)
expect(rotatePersistedAnonymousDistinctId()).not.toBeNull()
expect(clearPersistedUnmergeableAnonymousEpoch()).toBe(true)
expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(false)
})
it('persists an unmergeable epoch across restarts until a clean rotation clears it', () => {
expect(persistAnonymousDistinctId(ANONYMOUS_ID_1)).toBe(true)
expect(persistUnmergeableAnonymousEpoch()).toBe(true)
expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(true)
expect(readPersistedAnonymousDistinctId()).toBe(ANONYMOUS_ID_1)
expect(rotatePersistedAnonymousDistinctId()).not.toBeNull()
expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(true)
expect(clearPersistedUnmergeableAnonymousEpoch()).toBe(true)
expect(hasPersistedUnmergeableAnonymousEpoch()).toBe(false)
})
🤖 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 `@src/main/lib/anonymousIdentity.test.ts` around lines 85 - 94, The test should
verify that the unmergeable epoch marker survives
rotatePersistedAnonymousDistinctId(). Add an assertion immediately after the
rotation confirming hasPersistedUnmergeableAnonymousEpoch() is true, while
preserving the existing assertion that clearPersistedUnmergeableAnonymousEpoch()
removes it.

Comment on lines +34 to +38
clearVerifiedLocalFirebaseUser: (origin: string) => {
verifiedLocalUsers.delete(origin)
return true
}
}))

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 | 🔵 Trivial | ⚡ Quick win

Add a revoke-failure case to this mock's repertoire.

clearVerifiedLocalFirebaseUser always succeeds here, so the fail-closed behavior discussed on src/main/lib/firebaseAuthIdentity.ts Lines 105-122 has no coverage. A verifiedLocalRevocation.succeeds toggle (mirroring verifiedLocalPersistence) plus a test asserting no re-bind after a failed revoke would pin it down — one small mock, one big net.

🤖 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 `@src/main/lib/firebaseAuthIdentity.test.ts` around lines 34 - 38, Add a
verifiedLocalRevocation.succeeds toggle to the firebaseAuthIdentity test mock,
mirroring verifiedLocalPersistence, and make clearVerifiedLocalFirebaseUser
return failure without deleting the user when the toggle is false. Add a test
covering failed revocation and assert the identity is not re-bound afterward,
exercising the fail-closed behavior in firebaseAuthIdentity.

Comment on lines +105 to +122
function revokeAcceptedLocalAuthorization(
webContents: WebContents,
reporter: Reporter,
origin: string | null,
state: ComfyDesktop2FirebaseAuthState,
userMismatch: boolean
): void {
if (
!origin ||
!isLoopbackOrigin(origin) ||
(state.status !== 'signed_out' && !userMismatch)
)
return
clearVerifiedLocalFirebaseUser(origin)
reporter.localReportingAuthorized = false
reporter.localExpectedUserId = null
mainVerifiedStates.delete(webContents)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Persistence failure here silently fails open, not closed.

clearVerifiedLocalFirebaseUser(origin) returns a boolean that is dropped on the floor. If the write/unlink fails, the on-disk binding survives while only the in-memory flags are cleared — and the very next main-frame commit calls refreshReporterAuthScope (Line 98), which re-reads that stale binding and hands localReportingAuthorized straight back to an origin whose trust was just revoked (same after a restart). That contradicts the fail-closed intent for persistence failures.

Suggest treating a failed revoke as an unmergeable/pending situation rather than a shrug — a revoke that doesn't stick is a trust trick.

🔒 Sketch: keep the reporter out of consensus when revocation can't persist
   ): void {
   if (
     !origin ||
     !isLoopbackOrigin(origin) ||
     (state.status !== 'signed_out' && !userMismatch)
   )
     return
-  clearVerifiedLocalFirebaseUser(origin)
+  const revoked = clearVerifiedLocalFirebaseUser(origin)
   reporter.localReportingAuthorized = false
   reporter.localExpectedUserId = null
   mainVerifiedStates.delete(webContents)
+  if (!revoked) {
+    // The stale binding would re-authorize this origin on the next commit.
+    reporter.eligible = false
+    reporter.active = false
+    reporter.state = { status: 'pending' }
+  }
 }
📝 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
function revokeAcceptedLocalAuthorization(
webContents: WebContents,
reporter: Reporter,
origin: string | null,
state: ComfyDesktop2FirebaseAuthState,
userMismatch: boolean
): void {
if (
!origin ||
!isLoopbackOrigin(origin) ||
(state.status !== 'signed_out' && !userMismatch)
)
return
clearVerifiedLocalFirebaseUser(origin)
reporter.localReportingAuthorized = false
reporter.localExpectedUserId = null
mainVerifiedStates.delete(webContents)
}
function revokeAcceptedLocalAuthorization(
webContents: WebContents,
reporter: Reporter,
origin: string | null,
state: ComfyDesktop2FirebaseAuthState,
userMismatch: boolean
): void {
if (
!origin ||
!isLoopbackOrigin(origin) ||
(state.status !== 'signed_out' && !userMismatch)
)
return
const revoked = clearVerifiedLocalFirebaseUser(origin)
reporter.localReportingAuthorized = false
reporter.localExpectedUserId = null
mainVerifiedStates.delete(webContents)
if (!revoked) {
// The stale binding would re-authorize this origin on the next commit.
reporter.eligible = false
reporter.active = false
reporter.state = { status: 'pending' }
}
}
🤖 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 `@src/main/lib/firebaseAuthIdentity.ts` around lines 105 - 122, Update
revokeAcceptedLocalAuthorization to inspect the boolean result from
clearVerifiedLocalFirebaseUser. When persistence fails, retain a fail-closed
pending/unmergeable state that prevents refreshReporterAuthScope and subsequent
restarts from restoring localReportingAuthorized or including the reporter in
consensus until revocation succeeds.

… binds

The no-source branch of bindMainVerifiedFirebaseUser had no callers —
every verified flow binds through a hosted view. Dropping it keeps all
main-verified binds on the consensus path.

@deepme987 deepme987 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Agent Review — focused on the trust core (the "can an untrusted frame spoof a trusted identity?" question). Excellent, security-critical work; the answer is no at every layer. Nothing blocks merge from my read.

What I verified:

  • Trust classificationisTrustedCloudUrl is https-only, rejects username/password and non-empty port, exact-host allowlist + a correctly-anchored *.testingcloud.comfy.org check (leading-dot endsWith + apex exclusion, so eviltestingcloud.comfy.org and …comfy.org.attacker.com both fail). (inline)
  • Main is the trust authority — renderers report auth state; main decides (authorized only if trusted-cloud URL or Desktop-verified loopback; else ignored, fail-closed).
  • IPC frame-binding — the firebaseAuthState handler accepts a report only from the sender's main frame (senderFramemainFrame), so a sub-iframe can't report; payload is validated (status enum + normalized, non-illegal userId) before authorization is even applied. (inline)
  • Verified-loopback is genuinely loopback-onlynormalizeLoopbackOrigin rejects any non-loopback origin, so an external origin can never get a verified-local binding; the preload monitor runs only on loopback pages and reads the actual Firebase IndexedDB (Desktop verifies persistence, not a renderer claim; >1 user → pending, never guesses). (inline)
  • Fail-closed on every race — navigation/frame swap (isSameFrame/settleFailedNavigation), detached hosts (isDestroyed filter), logout (revoke), and the privacy-critical one: an unmergeable identity conflict taints and, if the taint can't persist, durably discards the anonymous epoch so a conflicted ID is never wrong-merged nor resurrected untainted across a restart. (inline)

Bonus (not auth): the telemetry IPC is well-hardened — client/deployment axes are host-authoritative (stripped/resolved from the sender, never trusted from payload), and values are clamped with the larger JSON ceiling gated by an explicit key allowlist (not a _json suffix), so a renderer can't bypass the clamp by renaming a field.

Minor (non-blocking): *.testingcloud.comfy.org preview subdomains count as "trusted cloud" for auth reporting. They're first-party ephemeral preview envs and the report only affects telemetry identity (not privilege), so it's reasonable — just flagging it's a broad-ish trust grant.

Scope: I deep-read the trust core (trustedCloudUrl, the authorization model + fail-closed structure in firebaseAuthIdentity.ts, verifiedLocalFirebaseAuth.ts, the IPC binding, the preload monitor) but not the full 630-line reconcile() winner resolution line-by-line, nor the ~1,100 lines of tests. The PR cites an independent security/lifecycle review + 3,078 tests.

'testcloud.comfy.org'
])

export function isTrustedCloudUrl(value: string): boolean {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Solid trust boundary. https-only + rejecting username/password/port closes the credential-in-URL and proxy-port tricks, and the *.testingcloud.comfy.org check is correctly anchored (leading-dot endsWith + !== 'testingcloud.comfy.org' apex exclusion), so eviltestingcloud.comfy.org and x.testingcloud.comfy.org.attacker.com both fail. This is the single line the whole consensus's trust rests on — worth keeping it exact-match + anchored in any follow-up.

return typeof value === 'string' && value.length > 0 ? value : null
}

function firebaseAuthReporterFrame(event: IpcMainEvent): WebFrameMain | null {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is the key anti-spoof gate: auth-state reports are accepted only from the sender's main frame (senderFrame.processId/routingId ≡ mainFrame), so a malicious embedded sub-iframe can't report an identity. Combined with the payload validation (asFirebaseAuthState) and the reporter-authorization check downstream, an untrusted frame's report is dropped before it can reach consensus. Nicely layered.

return path.join(configDir(), VERIFIED_LOCAL_FIREBASE_AUTH_FILE)
}

function normalizeLoopbackOrigin(value: unknown): string | null {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Good airtight scoping: because this rejects any non-loopback origin (and requires url.origin === value, no path/query smuggling), an external/remote origin can never be persisted as a verified-local binding. So the "Desktop-verified loopback" trust path is genuinely loopback-only — the exact property that keeps a remote page from claiming a local identity.

epochTaintIsDurable = mainTelemetry.markAnonymousEpochUnmergeable()
if (!epochTaintIsDurable) return false
}
if (!mainTelemetry.discardUnmergeableAnonymousEpoch()) return false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The privacy-critical fail-closed step. When an identity conflict can't be tainted durably, discarding the anonymous epoch here means a conflicted anonymous ID is never merged to the wrong user and can't be resurrected untainted after a restart. This is the right call over trying to keep a possibly-conflicted epoch alive — ties cleanly into #1304's taint/discard primitives.

@benceruleanlu
benceruleanlu added this pull request to the merge queue Jul 29, 2026
Merged via the queue into main with commit 470269f Jul 29, 2026
12 checks passed
@benceruleanlu
benceruleanlu deleted the bl/gtm-93-e-firebase-auth-consensus branch July 29, 2026 23:02
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants