アーキテクチャ
システム概要
iOS アプリ / 外部エージェントクライアント -> api.<domain> -> API Gateway -> Lambda バックエンド -> Postgres
Web アプリ -> app.<domain> -> CloudFront -> SPA
ブラウザ / エージェント認証 -> auth.<domain> -> API Gateway -> Auth Lambda -> Cognito
ルートドメインのフォールバック -> <domain> -> CloudFront リダイレクト -> app.<domain>
基本原則
app、api、authはそれぞれ独立した公開ドメインを使う- Postgres を正本データストアとする
- iOS クライアントは、ローカル SQLite と同期を組み合わせたオフラインファーストを前提とする
- Web アプリ、iOS アプリ、外部エージェント向けインターフェースは、同じワークスペースのデータモデルを共有する
- 外部エージェントは
GET https://api.flashcards-open-source-app.com/v1/を起点にする
対応クライアント
app.flashcards-open-source-app.comで提供する Web アプリ- メインリポジトリに含まれる、ローカル SQLite ストレージを使う iOS アプリ
- Google Play で配布している Android アプリ
- 接続案内用エンドポイント、OTP による初期認証、
Authorization: ApiKeyに対応した外部エージェントクライアント
データモデル
workspacesworkspace_membersuser_settingsdevicescardsdecksreview_eventsapplied_operationssync_state
データフロー
Web
- ブラウザは
auth.<domain>経由でサインインする - Web アプリは
api.<domain>からワークスペースデータを読み込む - AI チャットのリクエストは
/chat/local-turnを通る - 復習結果の送信時に、書き込みとあわせてスケジューラ状態を更新する
iOS
- iOS アプリは、まず SQLite にローカル保存する
- ローカルの変更は送信待ちキュー(outbox)に積まれる
- 同期では
/v1/workspaces/{workspaceId}/sync/pushを使って変更をアップロードする - 同期では
/v1/workspaces/{workspaceId}/sync/pullを使ってリモート更新をダウンロードする - ローカルデータベースが変更を適用し、同期カーソルを進める
外部エージェント
- エージェントは
GET /v1/から開始する - OTP による初期認証は
auth.<domain>上で行う - エージェントは長期間有効な API キーを受け取る
- エージェントは
/v1/agent/meを読み込み、ワークスペース一覧を取得し、必要に応じて選択してから/v1/agent/sqlを使う
スケジューリング
Flashcards は、復習スケジューラとして FSRS を採用しています。
実装上のポイント:
- バックエンドと iOS では、対応する FSRS 実装をそろえている
- Web アプリはスケジューリング用のデータ契約を共有するが、3つ目の独立したスケジューラ実装は持たない
- ワークスペース単位のスケジューラ設定には、目標保持率(
desired retention)、学習ステップ(learning steps)、再学習ステップ(relearning steps)、最大間隔(maximum interval)、fuzzが含まれる - 実際の復習時刻は
reviewedAtClientを基準にする
詳しくは、メインリポジトリの FSRS スケジューリング仕様 を参照してください。
認証
- Cognito によるメール OTP
- ホスト版 Web アプリ向けの共有ドメインのブラウザセッション Cookie
auth.<domain>上の OTP による外部エージェント初期認証で、長期間有効な ApiKey を発行する- ローカル開発では
AUTH_MODE=none - 本番相当の認証では
AUTH_MODE=cognito
デプロイ構成
app.<domain>-> CloudFront + S3api.<domain>-> API Gateway + Lambda バックエンドauth.<domain>-> API Gateway + Lambda auth service- Postgres は AWS RDS で動かす
ルートドメインは別のマーケティングサイトとして運用できます。立ち上げ初期にまだ未使用であれば、インフラ側で一時的に app.<domain> へリダイレクトすることもできます。