feat(diagnostics): A.3 — redacted in-memory log sink + user-initiated export
Replaces the diagnostics scaffold with the production redaction policy + a user-initiated export path that satisfies DEC-016 (no automatic uploads). * `chanora_diagnostics::Redactor` applies the six policy rules to every captured log line: `$HOME` paths → `[home]`; IPv4 + IPv6 literals → `[ip]`; email-shaped strings → `[email]`; long base64-ish tokens → `[token]`; substrings registered with `KnownSecretRegistry` → `[REDACTED]`. The registry implements SS-AUD-003 defence-in-depth: storage adapters can register secrets as they cross out of the keyring so an accidental `Debug` print is still scrubbed at write time. * `InMemoryLogSink` is a bounded ring buffer (cap 500 lines in the bridge) that always passes lines through the redactor before storing them. `RedactingLogLayer` plugs it into `tracing- subscriber` alongside the existing logcat / fmt layers. * `DiagnosticExport::from_sink` builds a plaintext blob — already redacted — combining free-form metadata (crate version, target os/arch) with the retained log tail. `bridge::api:: export_diagnostics()` is the Flutter-facing entrypoint (`#[frb(sync)]`). * `bridge_init` now installs the redaction layer on both Android and desktop hosts, switching from the global `fmt::init()` shortcut to a layered `Registry` so the in-memory sink can sit side-by-side with the platform sink. * Flutter adds a bug-report icon to the AppBar; tapping it opens a scrollable monospace dialog with Copy and Close actions. New `diagnosticsAction` / `copyAction` / `closeAction` strings land in `app_en.arb` + `app_zh.arb`. Tests cover the redaction matrix (IPv4, IPv6, email, long tokens, known secret), the ring buffer capacity, and the full `DiagnosticExport::to_text()` round-trip — 9/9 green. Live-verified on Moto G: the dialog rendered a multi-line transcript with `[ip]`, `[token]`, `[home]` substitutions, the metadata block showed `target_os=android` `target_arch=aarch64`, and Copy placed the same text on the clipboard.
This commit is contained in:
@@ -12,6 +12,9 @@
|
||||
"connectAction": "Connect",
|
||||
"disconnectAction": "Disconnect",
|
||||
"refreshAction": "Refresh",
|
||||
"diagnosticsAction": "Diagnostics",
|
||||
"copyAction": "Copy",
|
||||
"closeAction": "Close",
|
||||
"startAudioAction": "Start audio",
|
||||
"pttHoldToTalk": "Hold to talk",
|
||||
"pttTransmitting": "Transmitting…",
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
"connectAction": "连接",
|
||||
"disconnectAction": "断开连接",
|
||||
"refreshAction": "刷新",
|
||||
"diagnosticsAction": "诊断信息",
|
||||
"copyAction": "复制",
|
||||
"closeAction": "关闭",
|
||||
"startAudioAction": "启动语音",
|
||||
"pttHoldToTalk": "按住说话",
|
||||
"pttTransmitting": "正在发送…",
|
||||
|
||||
@@ -139,6 +139,24 @@ abstract class AppL10n {
|
||||
/// **'Refresh'**
|
||||
String get refreshAction;
|
||||
|
||||
/// No description provided for @diagnosticsAction.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Diagnostics'**
|
||||
String get diagnosticsAction;
|
||||
|
||||
/// No description provided for @copyAction.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Copy'**
|
||||
String get copyAction;
|
||||
|
||||
/// No description provided for @closeAction.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Close'**
|
||||
String get closeAction;
|
||||
|
||||
/// No description provided for @startAudioAction.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -30,6 +30,15 @@ class AppL10nEn extends AppL10n {
|
||||
@override
|
||||
String get refreshAction => 'Refresh';
|
||||
|
||||
@override
|
||||
String get diagnosticsAction => 'Diagnostics';
|
||||
|
||||
@override
|
||||
String get copyAction => 'Copy';
|
||||
|
||||
@override
|
||||
String get closeAction => 'Close';
|
||||
|
||||
@override
|
||||
String get startAudioAction => 'Start audio';
|
||||
|
||||
|
||||
@@ -29,6 +29,15 @@ class AppL10nZh extends AppL10n {
|
||||
@override
|
||||
String get refreshAction => '刷新';
|
||||
|
||||
@override
|
||||
String get diagnosticsAction => '诊断信息';
|
||||
|
||||
@override
|
||||
String get copyAction => '复制';
|
||||
|
||||
@override
|
||||
String get closeAction => '关闭';
|
||||
|
||||
@override
|
||||
String get startAudioAction => '启动语音';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user