[interpretation] master_seed custody/復旧 — 既存資産の上に積む層と blob レイアウトの design call

着手前 orientation 完了。現 origin/main で既に done(PR #255/#257/#258): X25519 group 派生 TS port(`group-keys.ts`、`keys.rs` と byte 一致 + golden vector)/ in-memory `seed-session` + reload survival / 暗号 post の SPA 復号 + 「paste base64 key」unlock UI。

本タスクで積む不足層:
- **Ed25519 identity 派生(D-A)**: `quacker.ed25519.identity:v1`、Rust `keys.rs` に additive + TS、golden vector に ed25519 公開鍵を追加(cross-impl)
- **BIP-39**: seed↔24語(`@scure/bip39` / Rust `bip39`)、golden に mnemonic 追加
- **age 2 段 custody envelope** + IndexedDB 永続
- **passphrase 一級 + PRF 日和見 unlock UX**(現「paste base64」を置換)

design call(frozen spec の範囲内、commit message に記録):
1. blob レイアウト = **unlock-key 経由**(spec の確定モデル)。乱数 unlock-key を (a) passphrase の scrypt-age blob(scrypt 排他なので単独)、(b) `[passkey + recovery recipient]` の age blob に wrap。seed 本体は unlock-key で暗号化して IndexedDB。
2. recovery recipient = seed 派生 age recipient(`quacker.x25519.recovery:v1`、additive)。実 disaster recovery は BIP-39→seed 直再生、recovery recipient はその envelope 内表現(新しい秘密は増えない)。
3. **non-extractable CryptoKey は本 PR では不使用** — passphrase gating は unlock-key bytes の wrap が要り、non-extractable(bytes 取り出し不可)と両立しない。at-rest は age-wrapped ciphertext のみ(`idb-keyval`)で「平文 seed を不揮発化しない」を満たす。device-bound CryptoKey vault は design doc 通り defer。

baseline green(web 208 / channel keys 9)。commit は 3 本(派生+golden / envelope+永続 / unlock UX)予定。異論あれば SPA から。これから着手。