feat(ptt): close P0 unit-boundary gaps (SDD-088 / SDD-090 / SDD-091)

The P0 audit on v0.9.4-docs found three SDD items whose specified
software units were inlined into other types rather than packaged as
named units at the SDD-defined boundary:

* SDD-088 PttController — backend ownership + binding mutex +
  capability watch lived split between AudioEngine and
  ChanoraSession. Extracted into chanora_core::ptt::PttController.
  AudioEngine now owns only the cpal streams and the missed-key-up
  watchdog (SDD-092); the platform input backend, the active
  PttBinding, and the capability watch::Sender live in the
  controller. ChanoraSession::start_audio constructs the controller
  against the engine's gate; disconnect/reconnect/restart paths
  tear it down through stop().await before the engine.

* SDD-090 PttSanitizer — banned-field check was inlined as
  PttBanCheckVisitor inside RedactingLogLayer::on_event. Extracted
  into a generic PttSanitizer<L> tracing_subscriber::Layer that
  decorates an inner Layer (canonical pairing:
  RedactingLogLayer::with_sanitizer). The inner layer keeps its
  own structural ban check as defence-in-depth for bare-install
  callers.

* SDD-091 PttCapabilityBadge — Voice Bar badge was anonymous
  Padding/Tooltip/Row inside _AudioControlsState.build. Extracted
  into a public PttCapabilityBadge widget and added the
  SDD-091-specified per-platform explanation sheet that opens on
  the info-icon tap when the resolved capability is L0Focused.
  New l10n strings (en + zh) cover the sheet copy.

Tests:
  * 2 new unit tests for PttController (arm + descriptor watch)
  * 1 new unit test for PttSanitizer (end-to-end through a real
    tracing subscriber proving banned drop + safe forward)
  cargo test --workspace: 55 passed / 0 failed / 3 ignored
  cargo deny check: advisories ok, bans ok, licenses ok, sources ok
  flutter analyze: no issues
  tools/validate_docs.py: zero undefined refs, zero direct-layer
    violations (pre-existing 35 old-package-name warning unchanged)

No SDD/SAD/SRS doc changes — the contracts already named these
units; this commit aligns code unit boundaries with those contracts.
This commit is contained in:
EdisonJwa
2026-05-15 17:45:03 +08:00
parent 63f2901a6a
commit 9831624079
10 changed files with 747 additions and 170 deletions
@@ -253,6 +253,48 @@ abstract class AppL10n {
/// **'PTT: {level} ({backend})'**
String pttCapabilityBadge(String level, String backend);
/// No description provided for @pttCapabilityExplainTitle.
///
/// In en, this message translates to:
/// **'Push-to-Talk capability'**
String get pttCapabilityExplainTitle;
/// No description provided for @pttCapabilityExplainFocusedHeading.
///
/// In en, this message translates to:
/// **'Focused PTT'**
String get pttCapabilityExplainFocusedHeading;
/// No description provided for @pttCapabilityExplainFocusedBody.
///
/// In en, this message translates to:
/// **'Chanora is currently using Focused Push-to-Talk: the binding only fires while the Chanora window is focused. This is the universal fallback used on every platform when a global capture path is not available.'**
String get pttCapabilityExplainFocusedBody;
/// No description provided for @pttCapabilityExplainGoGlobalWindows.
///
/// In en, this message translates to:
/// **'On Windows, Global PTT is engaged automatically once you bind a key. No additional permission is required.'**
String get pttCapabilityExplainGoGlobalWindows;
/// No description provided for @pttCapabilityExplainGoGlobalMacos.
///
/// In en, this message translates to:
/// **'On macOS, Global PTT requires Input Monitoring permission. Open System Settings → Privacy & Security → Input Monitoring, allow Chanora, then re-bind the key.'**
String get pttCapabilityExplainGoGlobalMacos;
/// No description provided for @pttCapabilityExplainGoGlobalLinux.
///
/// In en, this message translates to:
/// **'On Linux, Global PTT requires a GNOME-Wayland desktop with the GlobalShortcuts portal. Re-bind the key and accept the desktop\'s shortcut dialog when it appears.'**
String get pttCapabilityExplainGoGlobalLinux;
/// No description provided for @pttCapabilityExplainGoGlobalGeneric.
///
/// In en, this message translates to:
/// **'Global PTT is not available in this environment. Focused PTT will keep working while the Chanora window has focus.'**
String get pttCapabilityExplainGoGlobalGeneric;
/// No description provided for @pttConfigureAction.
///
/// In en, this message translates to:
@@ -96,6 +96,32 @@ class AppL10nEn extends AppL10n {
return 'PTT: $level ($backend)';
}
@override
String get pttCapabilityExplainTitle => 'Push-to-Talk capability';
@override
String get pttCapabilityExplainFocusedHeading => 'Focused PTT';
@override
String get pttCapabilityExplainFocusedBody =>
'Chanora is currently using Focused Push-to-Talk: the binding only fires while the Chanora window is focused. This is the universal fallback used on every platform when a global capture path is not available.';
@override
String get pttCapabilityExplainGoGlobalWindows =>
'On Windows, Global PTT is engaged automatically once you bind a key. No additional permission is required.';
@override
String get pttCapabilityExplainGoGlobalMacos =>
'On macOS, Global PTT requires Input Monitoring permission. Open System Settings → Privacy & Security → Input Monitoring, allow Chanora, then re-bind the key.';
@override
String get pttCapabilityExplainGoGlobalLinux =>
'On Linux, Global PTT requires a GNOME-Wayland desktop with the GlobalShortcuts portal. Re-bind the key and accept the desktop\'s shortcut dialog when it appears.';
@override
String get pttCapabilityExplainGoGlobalGeneric =>
'Global PTT is not available in this environment. Focused PTT will keep working while the Chanora window has focus.';
@override
String get pttConfigureAction => 'Configure';
@@ -93,6 +93,32 @@ class AppL10nZh extends AppL10n {
return '对讲能力:$level$backend';
}
@override
String get pttCapabilityExplainTitle => '对讲能力说明';
@override
String get pttCapabilityExplainFocusedHeading => '聚焦对讲';
@override
String get pttCapabilityExplainFocusedBody =>
'Chanora 当前使用聚焦对讲:按键只在 Chanora 窗口处于聚焦时生效。这是所有平台在无法启用全局采集时的通用回退方案。';
@override
String get pttCapabilityExplainGoGlobalWindows =>
'在 Windows 上,绑定按键后会自动启用全局对讲,无需额外权限。';
@override
String get pttCapabilityExplainGoGlobalMacos =>
'在 macOS 上,启用全局对讲需要「输入监视」权限。请打开「系统设置 → 隐私与安全 → 输入监视」,授权 Chanora 后重新绑定按键。';
@override
String get pttCapabilityExplainGoGlobalLinux =>
'在 Linux 上,启用全局对讲需要带 GlobalShortcuts 门户的 GNOME-Wayland 桌面。请重新绑定按键,并在桌面弹出快捷键对话框时接受。';
@override
String get pttCapabilityExplainGoGlobalGeneric =>
'当前环境暂不支持全局对讲。聚焦对讲在 Chanora 窗口获得焦点时仍可正常使用。';
@override
String get pttConfigureAction => '配置';