Appearance
デモモード開発・検証ガイド (Demo Mode Guide)
本ドキュメントでは、本システムに実装されている「オフライン・ファースト」の設計思想に基づき、ローカルPCやデモ環境においてサーバーなしでアプリケーションの全機能をモック動作させる「デモモード」の仕組みと、そのテスト・検証手順を解説します。
1. デモモードの設計思想と制御フラグ
本システムは、ネット接続が不安定な放課後クラブ現場での運用を保証するため、ネットワーク接続が切断されても通常通り打刻や児童管理を行えるように設計されています。
1.1 制御フラグの仕組み
各アプリケーションで以下の環境変数またはプリプロセッサディレクティブを使用してデモモードの切り替えを制御します。
- フロントエンド (React / Vite): ビルド時の環境変数
.env.demoまたは環境変数VITE_DEMO_MODEで制御します。envコード内ではVITE_DEMO_MODE=trueimport.meta.env.VITE_DEMO_MODE === 'true'により判定し、本物の API クライアントではなく Mock API クライアント(MockAttendanceService,MockStudentService等)を依存関係注入(DI)します。 - デスクトップ (WinUI 3 / Avalonia): KioskはC#の条件付きコンパイル定数
KIOSK_DEMOでデモ機能を制御します。デモビルドではローカルGateway、模擬QR入力、模擬顔認証を使用できます。通常ビルドではこれらの模擬入力を表示・受理しません。
2. PWA/Web アプリでのデモモード起動とデバッグ
2.1 ローカル開発時のデモ起動
Vite 開発サーバー起動時にデモ用のスクリプトを実行します。
bash
# app/Guardian または app/Staff または app/Facility で実行
npm run demo:devこのコマンドは内部的に vite --mode demo を実行し、ローカルのポート 3000 または 5173 でデモ版 Web サーバーが立ち上がります。
2.2 モックサービスの実装構造
フロントエンドアプリ(Facility 等)におけるデモモードは、APIクライアント(Axios インスタンス等)に リクエストインターセプター(demoInterceptor.ts)を適用することで実装されています。
typescript
// src/services/demoInterceptor.ts
export const applyDemoInterceptor = (api: AxiosInstance) => {
api.interceptors.request.use(async (config) => {
const isDemo = String(import.meta.env.VITE_DEMO_MODE || 'false').toLowerCase() === 'true';
if (!isDemo) return config;
// デモモード時にリクエストを横取りし、ローカルモックデータをレスポンスとして返す
if (config.url?.includes('/attendance/init/')) {
const data = await getMockDashboardInit(facilityId);
throw { config, response: { status: 200, data, statusText: 'OK', config } };
}
return config;
});
};デモ用のスタブデータは、src/services/mockData.ts を中心としたモックデータモジュールから提供されます。
3. 打刻端末 (WinUI 3) のオフラインバッファ検証手順
玄関打刻端末(Kiosk App)において、通信遮断時のローカルバッファ保存と再接続時の自動同期が正しく機能するかどうかを検証するためのテストケースです。
3.1 テスト準備
- Kiosk App を
KioskDemoMode=trueのデモ構成で起動します。Windows版はフルスクリーンで起動し、初回起動時は「設定」から端末ごとの管理者PIN、施設ID、API URLを登録します。設定画面の「アプリ終了」は管理者認証後だけ利用できます。 - PC のネットワークカードを無効にするか、LAN ケーブルを抜いて「完全なオフライン状態」を作ります。
3.2 テストケース 1: オフライン時の打刻バッファリング
- IC カードリーダーに FeliCa カードをタッチ、または画面の対象者カードをタップして打刻を実行します。QRを検証する場合は設定でお迎えQRを有効化し、キーボードウェッジ式QRスキャナーを使用します(
HLQR:はデモビルドのみ)。 - 期待される挙動:
- 「受付完了」と対象者名が表示され、接続ステータスが「OFFLINE(ローカル保存)」になること。
- 暗号化された
offline_data.datと送信待ちキューに、打刻時刻を保持したレコードが追加されること。
3.3 テストケース 2: オンライン復帰時の自動バックグラウンド同期
- Kiosk App を起動した状態のまま、PC のネットワークを再び有効化(オンラインに復帰)します。
- 期待される挙動:
- 接続ステータスが「ONLINE」に切り替わること。
- バックグラウンド同期で未送信データが順次APIへ送信され、成功分だけキューから削除されること。
- API側の
AttendanceRecordに、オフライン時のタイムスタンプでレコードが生成されること。
4. デモ版シードデータの変更方法
検証用のアカウント情報やテスト児童データを変更したい場合は、以下のファイルを編集してください。
- PWA/Web (フロントエンドローカルモック):
src/services/mockData.tsを開き、テスト児童名(例: 「木更津 太郎」「袖ケ浦 花子」)や初期暗証番号を変更します。 - Kiosk (Avalonia / WinUI 3):
app/Kiosk/Common/Services/OfflineDataStore.csのデモ初期データ生成ロジックを確認します。デモ版はKiosk-Demoの専用保存領域を使用し、通常版の保存領域や実運用の初期データを共有しません。 - API (D1 データベースシード):
app/api/prisma/seed_sql.tsでシード用アカウントおよび児童の自動生成ロジックを変更します。
4.1 API デモシードのハッシュ最適化($demo$ プレフィックス)
大規模デモデータ(4,500アカウント等)のシード作成時、毎回高負荷な PBKDF2 演算を実行すると生成処理に数時間かかってしまいます。そのため、シードスクリプト内では暗号化ハッシュをその場で計算せず、$demo$[loginId] というプレフィックス付きのダミー文字列を password_hash に設定します。
APIの認証層(app/api/src/utils/auth.ts)は、ログイン試行時にこの $demo$ プレフィックスを検知すると、初回のみオンデマンドでハッシュ計算を実行し、ログイン成功時に現行の $v2$ ハッシュ形式(API側1,000回)へ再ハッシュしてDBに書き戻します。これはデモシードの生成を軽量化する仕組みであり、本番用のPBKDF2強度や外部Secret設定の代替ではありません。