入力フォームの権限設計でちょっとだけ賢くなった話
はじめに
MICINでエンジニアをしている小林です。
この記事は MICIN Advent Calendar 2025 の 16 日目の記事です。
前回は 舟見 さんの自社サービスを評価されるということでした。
この記事では、私が最近対応した入力フォームにおける「入力フィールドごとの権限設計」について紹介したいと思います。
対象となる入力フォーム機能は、すでにリリースから1年以上が経過しており、1つの入力フォームを複数の医療機関で共通利用する、少し複雑な運用をしています。その中で新たに、これまで存在しなかった「入力フィールドごとの権限設計」が必要になりました。
最初にもらった要件は、次のようなものでした。
はじめにもらった権限要件はシンプルなものだった
最初に受けた要件はとてもシンプルで、
「各フィールドごとに、各ユーザーロールで、編集可能かどうかを設定したい」
というものだけでした。
UIも、各フィールドに対してロール分のチェックボックスが並ぶ、非常に分かりやすいイメージです。
この要件を聞いたときに最初に思いついたのは、各フィールドに EditableRoles のような配列を持たせ、「編集できるロールを列挙する」という設計でした。要件から開発完了目標までの期間もあまり余裕がなかったため、当初はこの案で実装を進め始めました。
type Role string
const (
RoleAdmin Role = "Admin"
RoleDoctor Role = "Doctor"
RoleViewer Role = "Viewer"
)
type Field struct {
Title string
IsRequired bool
EditableRoles []Role
}
気づき
実装を進めながら、ふと普段から触れている AWS IAM の権限モデルを思い出しました。
IAMでは、
- s3:GetObject
- s3:PutObject
- dynamodb:Query
といったように、IAMではロールやユーザーに対して「許可されている操作(Action)」を列挙する形で権限を表現しています。
この仕組みを思い出した瞬間、「今考えている設計は、操作に対してロールを列挙する形で権限を表現しようとしていて、逆をやろうとしているな」という違和感が生まれました。
設計の見直し
最初の設計の問題点
改めて、入力フィールドに対して発生しうる操作を洗い出してみると、「編集」以外にも次のようなものが考えられます。
- 入力された値を閲覧する
- 入力フィールドに対してコメントをつける
将来的にはさらに増えるかもしれません。
このままEditableRolesという設計で進めると、操作が増えるたびにViewableRoles, CommentableRolesのようなフィールドを次々と増やしていくことになります。これは拡張性・保守性の面で不安がありました。
そこでプロダクトマネージャーに今後の機能拡張の見通しを確認したところ、「1年以内に、閲覧権限の制御機能を入れることを検討している」という回答をもらいました。
この時点で、「今の設計のまま進めると、確実に後からつらくなる」と判断し、設計を見直すことにしました。
再設計後
最終的に採用したのが、ロール × Enum で状態を表現する設計です。
権限をロールごとの配列で管理するのではなく、「状態」を表す Enum として持つ形に設計を変更しました。
- 閲覧不可(Hidden)
- 閲覧のみ(Readonly)
- 編集可(Editable)
この形にしたことで、「編集可かつ閲覧不可」といった、現実的にありえない状態を自然に排除でき、かつ権限が増えても Enum を拡張するだけで対応できるようになりました。
将来的にそこまで多様な権限パターンが増える想定はなかったため、IAM のように Action を細かく列挙する形にはせず、今回はあえてシンプルな Enum に留めました。
結果的に、当初のEditableRolesよりも、ずっと拡張性と安全性の高いモデルになりました。
type Permission string
const (
PermissionHidden Permission = "Hidden" // 閲覧不可
PermissionReadonly Permission = "ReadOnly" // 閲覧のみ
PermissionEditable Permission = "Editable" // 編集可
)
type Field struct {
Title string
IsRequired bool
Permissions map[Role]Permission
}
学び: 他プロダクトから学ぶ価値
初めから再設計後の形に至れなかった理由を考えてみると、最初の要件の「入力フィールドの編集権限」というテーマやそのUIに引っ張られすぎていたことにあると思っています。
このときは「状態をどうモデリングするか」ではなく「どう操作させるか」から設計を始めてしまっていました。
実装のしやすさや目の前の要件に引っ張られるほど、設計の重心がUIや操作に寄ってしまうのは、実務ではよくあることだと思います。
アジャイル開発では、最初から完成形の要件が渡されることは少なく、実装を進める中で少しずつ「本当に必要なもの」が見えてくる場面も多いと感じています。
今回の経験で強く感じたのは、こうした局面での「自分がこれまでに触ったことのある成熟したプロダクトの設計」を意識的に参照することの重要性です。AWS IAM のように長年運用されてきたサービスには、単なる実装テクニックではなく、状態空間の閉じ方や責務の切り分けといった設計上の知見が凝縮されています。
もちろん、それらをそのまま流用すればよいわけではありません。しかし一段抽象化して捉え直し、自分のプロダクトの文脈に合わせることで、局所最適な設計から一段引き上げることができる――今回の権限設計は、まさにその好例だったと感じています。
MICIN ではメンバーを大募集しています。
「とりあえず話を聞いてみたい」でも大歓迎ですので、お気軽にご応募ください!
Discussion