Skip to content

システムアーキテクチャ解説

本ドキュメントでは、「放課後リンク」プロジェクトの全体構造、採用テクノロジー、および各コンポーネント間の連携について詳細に解説します。


1. システム全体俯瞰

「放課後リンク」は、Cloudflare Workers を基盤としたエッジコンピューティング指向のバックエンドと、複数のクライアントアプリケーションおよび1つの API で構成される、モダンな SaaS 型システムです。

アーキテクチャ図(概念)


2. バックエンド (Backend)

バックエンドは、Hono + Cloudflare Workers によるエッジネイティブ構成です。

採用技術

  • Framework: Hono (Web Standards ベースの超高速フレームワーク)
  • Runtime: Cloudflare Workers (エッジ実行環境)
  • Database: Cloudflare D1 (分散 SQLite データベース)
  • ORM: Prisma (D1 Adapter を使用した型安全なクエリ)
  • Asynchronous Task: Cloudflare Queues(デプロイ環境の EVENT_QUEUE binding)。Queue bindingがないローカル・旧環境では ExecutionContext.waitUntil からWorker内処理へフォールバックします。

主な特徴

  1. サーバーレス & エッジネイティブ: 冷たい起動(Cold Start)が極めて速く、スケーラビリティに優れています。
  2. テナント分離 (Facility Scoping): ミドルウェアレベルで facility_id による厳格なフィルタリングを行い、マルチテナント環境におけるデータ漏洩を防止しています。
  3. ステートレス認証: JWT (JSON Web Token) を採用し、セッション管理を排除することでエッジでの高速な検証を実現しています。

3. クライアントアプリケーション (Clients)

各クライアントは、利用シーンに合わせて最適化されたテクノロジーを選択しています。

3.1 放課後リンク 管理ポータル (Management App)

  • 技術: C# / WinUI 3 (.NET 10) / Self-contained
  • 用途: 施設長・事務員による複雑な請求計算、補助金申請、統計管理。
  • 特徴: リッチなデスクトップ体験と、オフライン運用を前提にした堅牢なデスクトップ構成。

3.2 放課後リンク 打刻端末 (Kiosk App)

  • 技術: C# / WinUI 3 (Windows), Avalonia (Linux/Android)
  • 用途: 玄関に設置される打刻端末(児童の登下校・職員の出退勤)。
  • 特徴: Windows/Linux/Android 対応。NFC 読み取りやオフライン耐性を備えた堅牢な設計。

3.3 放課後リンク 職員ポータル (Staff App)

  • 技術: React / PWA
  • 用途: 職員による日誌作成、出席確認、お知らせ送信。
  • 特徴: インストール不要の PWA 構成。プッシュ通知によるリアルタイムな連携。

3.4 放課後リンク 保護者ポータル (Guardian App)

  • 技術: React / PWA
  • 用途: 保護者による欠席連絡、お迎え時間変更、施設からの通知確認。
  • 特徴: インストール不要の PWA 構成。QR コードによる簡単ログイン。

3.5 放課後リンク 施設運営アプリ (Facility App)

  • 技術: React / Vite / Capacitor
  • 用途: 施設職員による出席、日報、事故報告、在庫、通知の現場運用。
  • 特徴: Android対応とローカルキューによるオフライン同期。

3.6 放課後リンク Provider ポータル (Provider App)

  • 技術: React / Vite
  • 用途: 法人・テナント、施設、システム設定、全体監査ログの管理。
  • 特徴: APIの /v1/provider 配下を利用するサービス提供者向け管理画面。

4. セキュリティ & 認証モデル

認証フロー

  1. クライアントが POST /v1/auth/login で認証。
  2. サーバーは AccessToken (短期) と RefreshToken (長期) を発行。
  3. 以降の通信は Authorization: Bearer <Token> ヘッダーで行う。

アクセス制御 (RBAC)

  • SYSTEM_ADMIN: 全施設・全データの管理権限。
  • FACILITY_ADMIN: 自施設内の全データ管理、スタッフ管理権限。
  • STAFF: 自施設内の日常業務(出席管理、日誌等)へのアクセス。
  • GUARDIAN: 紐付けられた児童 of データのみへの限定的なアクセス。

テナント境界の保護

authMiddleware および facilityScopeMiddleware により、リクエストコンテキストにユーザー情報と施設IDを紐付け、Prisma のクエリ発行時に常に施設IDでのフィルタリングが強制される設計になっています。


5. データフロー & 非同期処理戦略

本システムでは、API の低レイテンシ化と耐障害性を担保するため、同期的処理と非同期的処理を厳密に分離しています。

5.1 Cloudflare KV (セッション & キャッシュ)

読み取り頻度が極めて高く、かつ変更頻度の低いデータは Cloudflare KV (Key-Value) にキャッシュされます。

  • JWT セッション検証: ログイン時に発行された JWT の有効性および失効リストを KV で保持し、毎リクエスト時の D1 データベースへの照会を回避します。
  • 施設設定キャッシュ: 各施設(テナント)の打刻判定ルールや IP 制限などの設定を KV で保持し、エッジでミリ秒未満の判定を可能にします。

5.2 非同期イベント処理(Queue / waitUntil)

入退室打刻のように「即時レスポンスが求められるが、後続の処理(FCM プッシュ通知など)に遅延が許容される処理」は、publishEvent から非同期で実行されます。デプロイ環境では EVENT_QUEUE が設定されていればCloudflare Queuesへ送信し、ローカルまたはbinding未設定環境では同じ処理を ctx.waitUntil に登録します。

5.3 キオスク端末のオフライン対応と一括同期 (Sync API)

ネットワーク一時切断に対する耐障害性を高めるため、キオスク端末は暗号化ローカルファイルと送信待ちキューを使う「ローカル・ファースト」構成になっています。実装は app/Kiosk/Common/Services/OfflineDataStore.csoffline_data.dat です。

  1. オフライン打刻の記録: ネットワーク未接続時も、児童・職員の打刻を暗号化ファイルへ保存し、画面に「OFFLINE(ローカル保存)」を表示します。固定の打刻音や音声ガイダンスには依存しません。
  2. 接続検知とバッファ送信: SyncEngine が一定間隔で接続を確認し、復旧後に POST /v1/kiosk/attendance へ送信待ちデータをFIFO順で送信します。成功確認できた項目だけを削除し、失敗項目は保持して再試行します。
  3. べき等性の担保: 各送信項目に X-Idempotency-Key を付与し、API側で再送による重複登録を防止します。打刻時刻は同期時刻ではなく、端末で記録したUnixミリ秒を送信します。

5.4 補助金単価データの動的配信と耐障害性(レジリエンス)設計

各自治体の補助金交付要綱改定に伴う単価調整の保守性を高めつつ、デスクトップアプリ(WinUI 3)側の計算処理の安定稼働を両立するため、API 配信とローカル JSON キャッシュの「二重化」によるレジリエンス設計を採用しています。

  1. 動的 API 配信と管理ポータル編集:
    • 補助金計算に必要な金額設定群は Cloudflare D1 に格納され、/v1/subsidy-rates エンドポイントを介して WinUI 3 アプリに動的に配信されます。
    • 要綱改定時は、WinUI 3 管理ポータルの設定画面から GUI 経由で一括編集し、POST リクエストにより一括で DB に保存(upsert トランザクション処理)されます。
  2. ローカル JSON 同期保存(オフライン用):
    • WinUI 3 ポータル上でユーザーが単価を変更して保存した際、API への送信が成功すると同時に、アプリの実行ディレクトリ内のローカル設定ファイル config/subsidy_rates.json も最新の単価マップで自動更新されます。
  3. 起動・計算時のフォールバック処理:
    • WinUI 3 アプリの補助金試算エンジン(SubsidyEstimatorService)は、起動時または計算開始時に API /v1/subsidy-rates から最新の単価マップの取得を試みます。
    • 万が一、ネットワーク一時切断やオフラインモードで API 通信が失敗した場合には、例外をキャッチしてローカルの config/subsidy_rates.json のデータをフォールバックとして自動ロードし、計算処理を滞りなく継続します。

関連ドキュメント

放課後リンク 開発プロジェクト