背景
同ドメインの Misskey マルチカラムクライアント onodai145/tsumugi(Tauri v2 + Rust + Svelte)とのアーキテクチャ比較で、トークン封じ込めの「機械的な担保」に差があることが分かった。
notedeck は AccountPublic(hasToken: boolean、src/bindings.ts:2285)でフロントへのトークン露出を型レベルで防げているが、tsumugi はさらに一段深く、**「漏れない設計」ではなく「漏れたら CI が落ちる仕組み」**まで持っている。
tsumugi 側の実装(参考):
api/client.rs — クライアント構造体の Debug 実装で token を <redacted> に伏せる(ログ・panic メッセージ経由の漏洩防止)
lib.rs の generates_frontend_bindings テスト — 生成された TS bindings に token: フィールドが含まれないことを assert!(!ts.contains("token:")) で検証
- エラー型のコメントで「token 等の機微情報は含めない」を規約化
notedeck 側の現状ギャップ
Account が #[derive(Debug)] で token を素通し(notecli src/models.rs:17-29)。Drop での zeroize はあるが、{:?} でログに出せば平文で漏れる。AuthResult(models.rs:1045-1051)も同様。
- bindings スナップショットテストは「陳腐化検知」のみ(
src-tauri/tests/bindings_snapshot.rs)で、内容の不変条件(アカウントトークン非露出)を検証していない。将来誰か(未来の自分や AI エージェント含む)が Account をうっかり specta export しても CI は通ってしまう。
accounts.token TEXT NOT NULL 列が schema に残存(notecli migrations/V1__initial_schema.sql:8)。keychain 移行済み・clear_token()(db.rs:309)はあるが、平文トークンの受け皿が DB に残り続けている。
提案
参考
tsumugi の該当実装: https://github.com/onodai145/tsumugi (src-tauri/src/api/client.rs, src-tauri/src/lib.rs の bindings テスト)
背景
同ドメインの Misskey マルチカラムクライアント onodai145/tsumugi(Tauri v2 + Rust + Svelte)とのアーキテクチャ比較で、トークン封じ込めの「機械的な担保」に差があることが分かった。
notedeck は
AccountPublic(hasToken: boolean、src/bindings.ts:2285)でフロントへのトークン露出を型レベルで防げているが、tsumugi はさらに一段深く、**「漏れない設計」ではなく「漏れたら CI が落ちる仕組み」**まで持っている。tsumugi 側の実装(参考):
api/client.rs— クライアント構造体のDebug実装で token を<redacted>に伏せる(ログ・panic メッセージ経由の漏洩防止)lib.rsのgenerates_frontend_bindingsテスト — 生成された TS bindings にtoken:フィールドが含まれないことをassert!(!ts.contains("token:"))で検証notedeck 側の現状ギャップ
Accountが#[derive(Debug)]で token を素通し(noteclisrc/models.rs:17-29)。Dropでのzeroizeはあるが、{:?}でログに出せば平文で漏れる。AuthResult(models.rs:1045-1051)も同様。src-tauri/tests/bindings_snapshot.rs)で、内容の不変条件(アカウントトークン非露出)を検証していない。将来誰か(未来の自分や AI エージェント含む)がAccountをうっかり specta export しても CI は通ってしまう。accounts.token TEXT NOT NULL列が schema に残存(noteclimigrations/V1__initial_schema.sql:8)。keychain 移行済み・clear_token()(db.rs:309)はあるが、平文トークンの受け皿が DB に残り続けている。提案
Account/AuthResultに手書きDebug実装(token を<redacted>に)bindings_snapshot.rsに不変条件テストを追加: 生成 TS に raw トークンフィールドが出ないことを assert。CreatedApiToken.token(ローカル HTTP API 用・発行時 1 回のみ返す設計)は意図的な露出なので allowlist 化するaccounts.token列を NULL 許容化 or 削除し、平文トークンの永続経路を閉じる(新規行が常に空であることの担保)参考
tsumugi の該当実装: https://github.com/onodai145/tsumugi (
src-tauri/src/api/client.rs,src-tauri/src/lib.rsの bindings テスト)