Skip to content

[editor] セッションのライフサイクル API が 3 つとも呼び出し元ゼロで、isActive が false に戻る経路が無い #268

Description

@shinyaoguri

2026-08 レビューの残件トリアージ (#243) で #237 (タブ凍結時の二重インスタンス) を検証した際に見つかった、その前提となる潜在バグ#237 の段階 2 を設計するには先にこちらを決める必要があるので分離して起票する。

事実

packages/editor/src/services/SessionStorageService.ts の次の 3 メソッドは、リポジトリ全体で呼び出し元がゼロ (grep 確認済み):

メソッド 位置 本来の役割
updateSessionActivity() :289-297 lastActiveAt の heartbeat
markSessionInactive() :302-316 isActive を false に戻す
getInstanceId() :386-390 インスタンス同定

結果として session.isActivecreateSession / resumeSessiontrue にされるだけで、false に戻る経路が存在しません

さらに resumeSession (:250-268) は:

session.isActive = true;
session.instanceId = this.instanceId;   // :259-260 — 既存値を無条件で上書き

既存の instanceId との照合を一切せずに上書きします。

なぜ問題か

「このセッションを今このタブが握っているか」を判定する材料が実質死んでいます。#237 の本質的な修正 (二重インスタンスの検出) は「元のタブがまだ生きているか」の判定を必要としますが、その判定基準となる isActive / lastActiveAt が機能していないため、#237 の段階 2 だけを先に実装できません

あわせて確認された関連事実 (#237 側)

  • SingleInstanceGuard.instanceId (:29) と SessionStorageService.instanceId (:48) は別々の crypto.randomUUID()。修正時にどちらを権威にするか設計判断が要る
  • appendEvent の ConstraintError は :535-545preventDefault() + stopPropagation() してログも警告も出さずに握り潰される。事故が起きても完全に不可視

対応案

  1. 可視化だけ先に (安価): ConstraintError の握り潰しに console.warn + 既存イベントとの hash 比較を足す。1 ファイル ~20 行。今は完全に無言なので、これだけでも価値がある
  2. ライフサイクルの復活: updateSessionActivity を実際に配線 (heartbeat) し、markSessionInactivebeforeunload / タブクローズで呼ぶ。instanceId の権威を 1 つに寄せる
  3. 2 の上で [editor] タブ凍結時に SingleInstanceGuard をすり抜けた二重インスタンスがチェーンを壊しうる #237 段階 2 (resume 時の照合と read-only フォールバック) を実装

死んだ API を消す選択肢もありますが、#237 の解決に必要なのでまず配線を検討すべきです。

関連

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcode-review2026-07 多角レビュー由来pkg:editorpackages/editorseverity:medium中程度の問題

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions