From cd9dc0c8f66992d627c15805592200b2163acedb Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:12:43 +0800 Subject: [PATCH 1/7] Format the repo scripts `dart format . --set-exit-if-changed` reformats three files under scripts/, which fails the Dart Format CI job on main and therefore on every PR. No behaviour change; formatting only. --- scripts/check_version.dart | 1 + scripts/create_change.dart | 1 + scripts/create_version.dart | 1 + 3 files changed, 3 insertions(+) diff --git a/scripts/check_version.dart b/scripts/check_version.dart index 65b2055a5..57fd3bafc 100755 --- a/scripts/check_version.dart +++ b/scripts/check_version.dart @@ -1,4 +1,5 @@ #!/usr/bin/env dart + /* * Copyright 2025 LiveKit * diff --git a/scripts/create_change.dart b/scripts/create_change.dart index ab5b0c260..ae2cc94c9 100755 --- a/scripts/create_change.dart +++ b/scripts/create_change.dart @@ -1,4 +1,5 @@ #!/usr/bin/env dart + /* * Copyright 2025 LiveKit * diff --git a/scripts/create_version.dart b/scripts/create_version.dart index 6d0dd75e7..9af2bf2a6 100755 --- a/scripts/create_version.dart +++ b/scripts/create_version.dart @@ -1,4 +1,5 @@ #!/usr/bin/env dart + /* * Copyright 2025 LiveKit * From 129e91bf2ec33c0d7af18527bbfe55d12846661d Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:12:43 +0800 Subject: [PATCH 2/7] Await the cached-token future inside CachingTokenSource.fetch `fetch` returned `resultFuture` from inside its `try` block, so the surrounding `catch` could not observe a failure from that future and the `finally` clause removed the in-flight entry before it settled. Dart 3.13's analyzer flags this as `unawaited_return_in_try_block`, failing the Dart Analyze CI job; un-awaited async state updates are also a recurring source of bugs in this codebase. Both returns now `await` the future, so errors route through the existing catch and the in-flight map is cleaned up only once the request is done. The completer is completed immediately before each return, so the awaited future is already resolved and behaviour is unchanged. --- lib/src/token_source/caching.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/token_source/caching.dart b/lib/src/token_source/caching.dart index 2a7cdd345..f82831bcf 100644 --- a/lib/src/token_source/caching.dart +++ b/lib/src/token_source/caching.dart @@ -135,13 +135,13 @@ class CachingTokenSource implements TokenSourceConfigurable { final cached = await _store.retrieve(); if (cached != null && cached.options == options && _validator(cached.options, cached.response)) { completer.complete(cached.response); - return resultFuture; + return await resultFuture; } final response = await _wrapped.fetch(options); await _store.store(options, response); completer.complete(response); - return resultFuture; + return await resultFuture; } catch (e, stackTrace) { completer.completeError(e, stackTrace); rethrow; From 43e07d997018638bede7e3869b255e40e464bc16 Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:13:00 +0800 Subject: [PATCH 3/7] Add changeset for CachingTokenSource await fix --- .changes/caching-token-source-await | 1 + 1 file changed, 1 insertion(+) create mode 100644 .changes/caching-token-source-await diff --git a/.changes/caching-token-source-await b/.changes/caching-token-source-await new file mode 100644 index 000000000..2f9b3c493 --- /dev/null +++ b/.changes/caching-token-source-await @@ -0,0 +1 @@ +patch type="fixed" "CachingTokenSource.fetch now awaits its result inside the try block, so failures reach the catch clause and the in-flight request entry is cleared only once the request settles" From a2ae291fbbbe0a9335b558f4eb947cc05742d568 Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:23:46 +0800 Subject: [PATCH 4/7] Commit the analyzer excludes Flutter's migrator insists on `AnalysisOptionsMigration` in flutter_tools appends build/**, android/**, ios/**, web/**, windows/**, macos/** and linux/** to analysis_options.yaml on every `flutter analyze`, `pub get` and `run`. It is unconditional -- there is no feature flag or config to disable it -- so the file showed up as modified after any Flutter command. Committing the patterns makes the migrator a no-op. It also documents the one that matters here: web/ holds the E2EE worker sources, not just assets, so excluding it silently drops them from analysis. That already happens in CI today, because `flutter analyze` runs the migrator before analyzing; the following commit restores that coverage explicitly. --- analysis_options.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/analysis_options.yaml b/analysis_options.yaml index b7cb2942b..1c0c39cf8 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -33,6 +33,18 @@ analyzer: # Manager is enabled and this package ships Package.swift. - build/** - example/build/** + # Flutter's AnalysisOptionsMigration (flutter_tools) appends these seven + # patterns to this file on every `flutter analyze`/`pub get`/`run`. There is + # no opt-out, so they are committed here to stop the file being rewritten. + # Note this excludes web/, which in this package holds real Dart source (the + # E2EE worker) rather than just assets -- CI analyzes it explicitly with + # `dart analyze web/`, which does not run migrators. + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** linter: rules: From e5bc639869ea4bd2a78749ecb31e9a36765bb3fe Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:25:16 +0800 Subject: [PATCH 5/7] Keep the web/ E2EE sources under analysis The root analysis_options.yaml now excludes web/**, because Flutter's AnalysisOptionsMigration forces that pattern in and cannot be turned off. In this package web/ is not assets -- it holds the E2EE worker sources -- so that exclusion silently dropped them from analysis. This already happened in CI, since `flutter analyze` runs the migrator before it analyzes. Passing the path explicitly does not help: `dart analyze web/` still honours the root exclude and reports success on a file with a type error. Giving web/ its own analysis_options.yaml creates a separate context that is genuinely analyzed. Verified by appending a deliberate type error to web/e2ee.logger.dart, which the new setup reports and the old one did not. The file mirrors the root's error overrides and its formatter settings (page_width 120, trailing_commas preserve) so `dart format` output is unchanged, and CI gains a `dart analyze web/` step. --- .github/workflows/build.yaml | 6 ++++++ web/analysis_options.yaml | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 web/analysis_options.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 55ebf58ee..61f8f2616 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -66,6 +66,12 @@ jobs: - uses: ./.github/actions/setup-flutter - name: Dart Analyze Check run: flutter analyze + # `flutter analyze` runs Flutter's AnalysisOptionsMigration first, which + # forces `web/**` into analysis_options.yaml. This package keeps real Dart + # source there (the E2EE worker), so analyze it separately -- `dart + # analyze` does not run migrators. + - name: Dart Analyze Check (web sources) + run: dart analyze web/ dart-test-check: name: Dart Test diff --git a/web/analysis_options.yaml b/web/analysis_options.yaml new file mode 100644 index 000000000..49bf25b0e --- /dev/null +++ b/web/analysis_options.yaml @@ -0,0 +1,33 @@ +# +# Copyright 2025 LiveKit +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# The repository-root analysis_options.yaml has to exclude `web/**`: Flutter's +# AnalysisOptionsMigration appends that pattern on every `flutter analyze` and +# offers no way to opt out. These files are real Dart source (the E2EE worker), +# not web assets, so this file gives them their own analysis context and keeps +# them covered. CI analyzes them via `dart analyze web/`. + +include: package:lints/recommended.yaml + +analyzer: + errors: + constant_identifier_names: ignore + use_super_parameters: ignore + avoid_print: ignore + deprecated_member_use_from_same_package: ignore + +formatter: + page_width: 120 + trailing_commas: preserve From 4f448ebaf2bc2be778bebe059ed9912a32adcc6f Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:37:05 +0800 Subject: [PATCH 6/7] Shorten changeset entry --- .changes/caching-token-source-await | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/caching-token-source-await b/.changes/caching-token-source-await index 2f9b3c493..3e8546c02 100644 --- a/.changes/caching-token-source-await +++ b/.changes/caching-token-source-await @@ -1 +1 @@ -patch type="fixed" "CachingTokenSource.fetch now awaits its result inside the try block, so failures reach the catch clause and the in-flight request entry is cleared only once the request settles" +patch type="fixed" "CachingTokenSource.fetch now awaits its result, so errors surface and the in-flight entry is cleared correctly" From ff5086357f7f2146a4998ef7e9e01611c7e655e0 Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 27 Aug 2026 01:42:59 +0800 Subject: [PATCH 7/7] Mirror the root linter rules into the web analysis config The web/ config only carried the analyzer and formatter sections, so the E2EE sources lost prefer_single_quotes, prefer_final_locals, unawaited_futures and discarded_futures. Confirmed via canary: those lints did not fire before this change and do now. web/ passes clean. --- web/analysis_options.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/web/analysis_options.yaml b/web/analysis_options.yaml index 49bf25b0e..50d5f9b78 100644 --- a/web/analysis_options.yaml +++ b/web/analysis_options.yaml @@ -28,6 +28,18 @@ analyzer: avoid_print: ignore deprecated_member_use_from_same_package: ignore +linter: + rules: + # Preference of the SDK + prefer_single_quotes: true + prefer_final_locals: true + unnecessary_brace_in_string_interps: false + avoid_print: true + + # Enforce this for correct async logic + unawaited_futures: true + discarded_futures: true + formatter: page_width: 120 trailing_commas: preserve