要約

  • ShareNotification は権限変更の server-side record であり、client 表示、人の理解、対象操作の成功を保証しない。
  • RFC 9670 の共有を検証するには、Principal の同一性、shareWith、受信者の myRights、isSubscribed、状態制御、実操作、失効後の拒否を分けて結ぶ必要がある。

利用者の端末に「共有されました」という通知が現れた。対象名も変更者も正しく、newRights には更新権限が含まれていた。ところが利用者が編集を送ると forbidden になった。

通知は誤っていなかった。通知が表したのは、server が共有変更を記録したという事実である。実際の編集は、その後の data-type-specific policy と enforcement に属していた。

RFC 9670 は、この違いを扱える材料を用意する。Principal は人、group、場所、room や projector のような resource を表せる。共有可能な data type は isSubscribed、myRights、shareWith を持つ。権限変更は ShareNotification で表現できる。

一方、RFC は共有対象や permission の細かさを決めない。各 data type が権限名と意味を定義する。統一されるのは形であって、すべての操作の意味ではない。

通知が持つもの、持たないもの

ShareNotification は server だけが作成する。object type、object Account、object ID、変更前後の myRights、作成時刻、changedBy、表示用の name を保持する。アクセスを失った利用者にも何を失ったか示せるよう、name は通知時点の値として残る。

この record は強いが、範囲がある。changedBy.principalId は null の場合がある。server は権限変更時に通知を作るべきだが、group Principal 由来の大量変更では、過剰になるなら省略できる。複数通知を coalesce し、保存上限を設け、古いものを期限切れにすることもできる。上限到達時に最古の通知を削除できるが、RFC はそれが security change を見えなくする危険を指摘する。

したがって記録すべき状態は一つではない。created、coalesced、suppressed、expired、client-fetched、displayed、acknowledged を区別する。通知 ID は created の receipt であり、attention の receipt ではない。

Principal の表示名から人を推定しない

shareWith の key は Principal ID である。name や email は選択 UI に必要だが、強い本人証明ではない。RFC 9670 は、利用者が自分の Principal の表示情報を編集できると、別の利用者を装えると警告する。単純な重複名禁止では、似た Unicode や僅かな綴り違いを防げない。

共有 receipt は、表示名ではなく immutable ID、directory generation、Principal を収める Account、object Account の owner を結ぶべきである。Principal 集合の管理は RFC の範囲外であり、directory や user-management system に委ねられる。つまりその正当性を証明するのは local operator の仕事である。

owner は shareWith に入らない。owner rights は implicit だからだ。map だけを見て authority の全体を数える監査は、最初から不完全になる。

付与、実効権限、購読は別の状態

shareWith は Principal ごとに与える rights の map である。myRights は現在の user がその object について持つ rights を返す。両者は似た Boolean map でも、同じ観測ではない。

owner 側で grant を読んだら、recipient 側で myRights を読む。その後、read、update、destroy、admin など問題となる operation を限定して実行する。myRights の一つが true でも、別の operation の成功を借りてはならない。

isSubscribed は permission ではなく関心を表す。共有物に access できても、通常の一覧へ出さない選択があり得る。server が subscription を拒否しながら permission を維持する場合もある。「画面にない」と「開けない」は異なる障害である。

Session に含まれる Account や StateChange も購読境界に従う。未購読 resource の変化が push されないことを、権限がない証拠にしてはならない。

ifInState は共有 map の競合を止める

二人の管理者が同じ shareWith を読み、一人は A を追加し、もう一人は B を削除する。両者が map 全体を無条件で保存すれば、後の write が先の判断を消す。

RFC 8620 の ifInState は、client が読んだ state と server の current state が同じ場合だけ /set を進める。違えば stateMismatch で止まる。response は updated と notUpdated、oldState と newState を分ける。

保存すべき receipt は、object ID、旧 state、map hash、precondition、個別結果、新 state である。state token は concurrency control であり、actor、理由、通知、人の理解、操作成功を記述する audit log ではない。

失効は server の未来を閉じる

Principal を shareWith から除き、recipient の myRights が下がり、新しい operation が拒否されることを確認すれば、その service の live authority は閉じたと言える。

それ以前に正当に export された file、offline copy、service の外にある cache までは消えない。RFC 9670 は copy erasure を規定しない。失効の statement は「いつ、どの generation から、どの新規 operation を拒否したか」に限定する必要がある。

security considerations はこの境界を補強する。短時間の unlocked client access で攻撃者の Principal を追加すれば、侵害を持続化できる。sharing change を大量に起こせば通知資源を枯渇させられる。Principal 登録が無制限なら、誤共有、望まない共有、通知 spam が増える。

共通モデルは最小仕様である。その上に identity、concurrency、visibility、enforcement、copy policy の running evidence を積まなければ、「通知済み」は成功の省略語になってしまう。

情報源