訪問看護ステーション向けの業務管理システム。利用者管理・訪問記録(電子カルテ)・スケジュール・ケアプラン・請求管理・評価(BI/FIM)・LIFE連携を統合。マルチテナント対応で事業所ごとにデータ分離。

現状: UI/UXはほぼ完成。認証・テナント分離は実装済みだが、多くのデータ画面はモックで動作中。

全体構造(セキュリティ3層)

ユーザーのリクエストはブラウザから3層のセキュリティを通過してFirestoreに到達する。

ユーザー(ブラウザ) 看護師 / 管理者(owner) HTTPS LAYER 1 — EDGE MIDDLEWARE middleware.ts — Cookie存在チェック ・Cookie あり → 通過 ・Cookie なし + 保護パス → /login にリダイレクト ※ Edge Runtime では firebase-admin 使用不可のため Cookie の「存在」のみ確認 LAYER 2 — SERVER COMPONENT 検証 verifySessionCookie — IDトークン検証 ・adminAuth.verifySessionCookie(cookie, true) → 署名検証 + 失効確認 ・Custom Claims から tenant_id / role を取得 検証OK LAYER 3 — FIRESTORE SECURITY RULES tenant_id 一致を全 read/write で強制 ・allow read: if isAuth() && resource.data.tenant_id == getTenantId() → 自分のテナントのデータしか見えない Firebase Firestore 永続化層

マルチテナント分離の仕組み

サインアップ時の3ステップ処理 1 Auth作成 Firebase Auth で ユーザー登録 2 トランザクション テナント作成 + ユーザー作成(role: owner) 3 Custom Claims tenant_id + role を IDトークンに埋め込む テナント分離の全体像 事業所A(tenant_id = A) 患者 1, 2, 3 看護師 X, Y 訪問記録... A のみ データ壁 事業所B(tenant_id = B) 患者 4, 5, 6 看護師 Z, W 訪問記録... B のみ Firestore Security Rules(共有層) AのユーザーはAのデータのみ参照可 / BのユーザーはBのデータのみ参照可 → tenant_id の一致をルールで強制 アクセス不可

認証フロー

ユーザー Next.js Firebase ① メール/パスワード入力 signInWithEmailAndPassword ② IDトークン取得 ③ POST /api/auth/session(IDトークン送信) createSession Cookie() 有効期限: 5日 httpOnly / secure / lax ④ Session Cookie セット(Set-Cookie) ⑤ /dashboard へ遷移 verifySession Cookie() → tenant_id role 取得 ロール階層: owner > admin > staff

データモデル(ER図)

tenants 事業所 1:N users スタッフ | role: owner/admin/staff 1:N patients 利用者 | insurance_type / care_level 1:N visits 訪問スケジュール | date / staff_id claims 請求 | status / total_amount 1:N medications 服薬情報 1:N vital_records バイタル記録 1:N family_contacts 家族連絡先 1:N care_plans ケアプラン 1:N visit_records 訪問記録(電子カルテ) 1:N visit_records フィールド vitals / observations / care_provided patient_condition / next_visit_notes arrived_at / departed_at

訪問記録入力(3ステップフォーム)

1 基本情報 2 バイタル 3 観察・実施 ステップ1: 基本情報 利用者選択 担当スタッフ 訪問日 到着時間 退出時間 次へ ステップ2: バイタルサイン 体温 血圧(上/下) 脈拍 SpO2 呼吸数 次へ ステップ3: 観察・実施内容 stable improving declining requires_attention 観察内容(自由記述) 実施したケア(自由記述) 次回訪問への申し送り

実装状況マップ

実装済み モック(未接続) 注意事項 全体進捗: 5 / 15 実装済み 実装済み 認証(login / signup / logout) 完了 テナント作成・Custom Claims 完了 Session Cookie(5日有効) 完了 サイドバー / ヘッダー / モバイルナビ 完了 Firestore Security Rules 完了 モック(未接続) 利用者一覧・詳細(PATIENTS定数) 訪問記録の保存(setTimeout) スケジュール管理 ケアプラン 評価入力(BI/FIM) アウトカム管理 LIFE連携 請求管理・帳票PDF・レポート
! Supabase migration ファイルも存在(将来の移行候補)

Firestore Security Rules(重要ルール)

function getTenantId() {
  return request.auth.token.tenant_id
}

allow read:
  if isAuth()
  && resource.data.tenant_id == getTenantId()

// → 自分のテナントのデータしか見えない

状態管理(シンプル構成)

グローバル状態管理ライブラリ(Redux / Zustand 等)は不使用。React 標準機能のみで構成。

認証状態
  • Layout 内で onAuthStateChanged
  • Firestore users/{uid} 取得
  • useState で保持
ページ内
  • useState
  • useMemo(検索・フィルタ)
フォーム
  • react-hook-form
  • zod(バリデーション)

技術スタック

カテゴリ 技術 用途
フレームワーク Next.js 15 App Router、Server Components、Middleware
認証 Firebase Auth メール認証 + Custom Claims でテナント情報付与
データベース Firestore NoSQL ドキュメント DB。Security Rules でテナント分離
サーバー firebase-admin Session Cookie の生成・検証(Server Action 内)
UI コンポーネント shadcn/ui Radix UI ベースのアクセシブルなコンポーネント
フォーム react-hook-form + zod バリデーション付きフォーム管理
移行候補 Supabase migration ファイルあり(将来の移行候補)
visitcare コード構成解説 — 最終更新: 2026-03-18