Covid19Radarのシーケンス図
ソースコードから書き起こしたシーケンス図です。間違っている可能性があります。
ソースコードから書き起こしたシーケンス図です。間違っている可能性があります。
@startuml | |
participant ユーザー as user | |
participant アプリ as app | |
participant 接触確認プラグイン as plugin | |
participant OS as os | |
participant サーバー as server | |
participant DB as db | |
==== 起動時 ==== | |
user -> app: 起動 | |
app -> plugin: Init | |
plugin -> plugin: ScheduleFetchAsync | |
plugin -> os | |
plugin <-- os | |
note over plugin: バックグラウンド処理開始\n後で説明 | |
app -> server: AppCenter | |
app -> plugin: IsEnabledAsync | |
app <-- plugin: bool | |
app -> plugin: ScheduleFetchAsync | |
note over plugin | |
trueだったらスケジュール | |
なんで2度も? | |
end note | |
app -> app: ユーザーデータを確認 | |
group ユーザーデータが存在しなければ | |
app -> app: チュートリアル開始 | |
end | |
group ユーザーデータが存在すれば | |
app -> app: ホームページ表示 | |
end | |
==== チュートリアル ==== | |
user <-- app: チュートリアル1表示 | |
user -> app: 次へボタン押下 | |
user <-- app: チュートリアル2表示 | |
user -> app: 次へボタン押下 | |
user <-- app: チュートリアル3表示 | |
user -> app: 次へボタン押下 | |
app -> server: RegisterUserAsync\nPOST /register\ncontentは空 | |
note over server | |
ユーザー登録 | |
UserUuidを生成 | |
UserUuidをseedに乱数文字列を生成: Secret | |
SecretをAES暗号化: ProtectSecret | |
end note | |
server -> db: ユーザーレコードを登録\nUserUuid\nProtectSecret | |
app <-- server: JSON応答\nSecret,UserUuid,JumpConsistentSeed | |
app -> os: ユーザーデータを生成し永続化 | |
user <-- app: プライバシーポリシー表示 | |
note over app | |
うーん | |
end note | |
user -> app: 次へボタン押下 | |
user <-- app: チュートリアル4表示 | |
group 非同意ルート | |
user -> app: 非同意 | |
app -> os: 接触通知は無効とユーザーデータに書き込んで保存 | |
end | |
group 同意ルート | |
user -> app: 同意 | |
group iOS | |
user <- app : Loading画面表示 | |
app -> plugin: StartAsync\n接触確認APIを開始 | |
plugin -> os: iOS: SetExposureNotificationEnabledAsync(true) | |
note over os | |
TEKから10~20分ごとにRPIを生成してアドバタイズ | |
OS側でずっと広告処理を行う | |
end note | |
group while | |
app -> app: 1秒待機 | |
app -> plugin: StartAsync\n接触確認APIを開始 | |
plugin -> os: iOS: SetExposureNotificationEnabledAsync(true) | |
note over app: 重要なことなので2度(略 | |
app -> plugin: GetStatusAsync\n状態取得 | |
plugin -> os: iOS: ExposureNotificationStatus | |
plugin <-- os: Status\nenum: Active,BluetoothOff,Disabled,Restricted | |
app <-- plugin: Status | |
group Status == Active | |
app -> os: 接触通知は有効とユーザーデータに書き込んで保存 | |
end | |
group Status == BluetoothOff | |
user <-- app: Bluetoothオフやで? | |
app -> app: 同意前に戻る | |
end | |
group 2回リトライしてダメだったら | |
user <-- app: Exposure Notificationを起動できませんでした\nOh! i18nされないハードコーディング!! | |
user -> app: OK | |
app -> app: アプリを落とす | |
end | |
end | |
end | |
group Android | |
note over app | |
ほぼiOSと同等だが | |
Bluetoothオフの場合に同意前に戻らない | |
end note | |
group 2回リトライしてダメだったら | |
app -> os: 接触通知は無効とユーザーデータに書き込んで保存 | |
app -> app: アプリは落とさずにチュートリアル5に進む | |
end | |
end | |
end | |
user <-- app: チュートリアル5表示 | |
user -> app: 通知(あり/なし)を選択\nIsNotificationEnabled = bool | |
app -> os: 通知有無をユーザーデータに保存 | |
user <-- app: チュートリアル6表示 | |
user -> app: ホーム/ヘルプページの表示を選択 | |
==== バックグラウンド処理 iOS ==== | |
app -> plugin: Init | |
plugin -> plugin: ScheduleFetchAsync | |
plugin -> os: BGTaskScheduler.Shared.Register\nコールバック登録\nUpdateKeysFromServer | |
plugin -> plugin: scheduleBgTask | |
plugin -> os: ENManager.AuthorizationStatus取得 | |
plugin <-- os: ENAuthorizationStatus | |
note over plugin: ENManager.AuthorizationStatus != ENAuthorizationStatus.Authorized\nならreturn | |
plugin -> os: BGTaskScheduler.Shared.Submit | |
note over os: バックグラウンド処理を依頼 | |
... | |
plugin <- os: UpdateKeysFromServer\nサーバーのキー情報を更新しよう | |
app <- plugin: FetchExposureKeyBatchFilesFromServerAsync\nサーバーからキー情報の回収よろー | |
group foreach (var serverRegion in SupportedRegions) | |
app -> app: DownloadBatchAsync | |
app -> app: GetTemporaryExposureKeyList | |
app -> server: GetCdnAsync\nGET /{container}/{region}/list.json | |
app <-- server: JSON応答\nTekList | |
group foreach tekItem in tekList | |
app -> os: LastProcessTekTimestamp取得 | |
app <-- os: LastProcessTekTimestamp | |
group LastProcessTekTimestampより新しいtekだったら | |
app -> server: GetTemporaryExposureKey\nGetCdnStreamAsync\nGET {tekItem.Url} | |
app <-- server: uuid生成および名前{uuid}.zipで\nファイル保存 | |
end | |
app -> os: LastProcessTekTimestamp更新 | |
end | |
app -> plugin: submitBatches | |
plugin -> plugin: PlatformDetectExposuresAsync | |
plugin -> plugin: GetConfigurationAsync | |
note over plugin: zip展開 -> .binファイルと.sigファイル | |
plugin -> os: iOS: DetectExposuresAsync | |
note over os | |
TEKからRPIを生成して突合 | |
end note | |
note over os | |
RPIの一致があればサマリ生成 | |
end note | |
plugin <-- os: detectionSummary:\nDaysSinceLastExposure\nMatchedKeyCount\nriskScoreSumFullRange\nmaximumRiskScoreFullRange | |
note over plugin: zip展開したファイルを削除 | |
app <- plugin: ExposureDetectedAsync | |
app -> plugin: getExposureInfo(GetInfo) | |
plugin -> os: iOS: GetExposureInfoAsync | |
plugin <-- os: Date\ntotalRiskScoreFullRange\nAttenuationValue\nTransmissionRiskLevel\nDuration | |
app <-- plugin: 同上 | |
app -> os: ユーザーデータのExposureInformationにExposureSummaryを追加 | |
group IsNotificationEnabled == true | |
user <-- app: 新型コロナウイルス陽性登録者との接触の可能性\n新型コロナウイルス陽性登録者と\n接触した可能性があります。詳細はこちら。 | |
user -> app: アプリ起動\nバックグラウンド動作なので | |
end | |
app -> app: zipファイル削除 | |
end | |
== 感染確認 == | |
user -> app: ホームページより感染確認ボタンを押下 | |
app -> app: ユーザーデータのExposureInformationより\n感染情報を確認 | |
group 感染情報が存在しない | |
user <-- app: 陽性者との接触は確認されませんでした | |
end | |
group 感染情報が存在する | |
user <-- app: 陽性者との接触確認 | |
note over app | |
以下メッセージ? | |
陽性者との接触一覧 | |
症状を入力して相談 | |
電話で症状を伝えて相談 | |
現在の症状などを、入力フォームまたはお電話にて、ご連絡ください。内容に応じて、帰国者・接触者外来等への受診を案内します。 | |
受診の際などに必要となる場合があるため、本画面のスクリーンショットの保存をお願いいたします。 | |
end note | |
end | |
== 陽性情報の登録 == | |
user -> app: ホームページより陽性情報の登録ボタンを押下 | |
user <-- app: 陽性情報の登録ページを表示 | |
note over app | |
以下メッセージ? | |
新型コロナウイルス感染症者等情報把握・管理支援システム(HER-SYS)から発行された処理番号を入力してください。 | |
過去14日間に本アプリであなたと接触した履歴のある人に通知が行きます。 | |
登録は匿名で行われ、氏名や連絡先など個人が特定される情報を登録する必要はありません。 | |
また、接触した場所の位置情報が記録や通知されることもありません。 | |
end note | |
user -> app: DiagnosisUidを入力\n処理番号 | |
app -> os: ユーザーデータのPendingDiagnosisにDiagnosisUidを追加 | |
app -> plugin: SubmitSelfDiagnosisAsync | |
plugin -> plugin: GetSelfTemporaryExposureKeysAsync\nPlatformGetTemporaryExposureKeys | |
plugin -> os: iOS: GetDiagnosisKeysAsync | |
plugin <-- os: TEK[]\nKeyData\nRollingStartNumber\RollingPeriod\nTransmissionRiskLevel | |
app <- plugin: UploadSelfExposureKeysToServerAsync(selfKeys) | |
app -> app: DiagnosisUidとTEK[]を関連付けして\nSubmissionを作成 | |
app -> server: PutSelfExposureKeysAsync\nPUT /diagnosis\nSelfDiagnosisSubmission | |
note over server | |
SubmissionNumber: DiagnosisUid | |
AppPackageName: AppInfo.PackageName | |
UserUuid | |
Platform | |
Regions: AppSettings.Instance.SupportedRegions | |
Keys: keys | |
VerificationPayload: DiagnosisUid | |
end note | |
note over server | |
diagnosisの正しさを検証 | |
UserUuidとAuthorizationヘッダーを検証 | |
AuthorizationヘッダーはUserUuidから生成されたもの | |
end note | |
server -> db: IDでユーザーを問い合わせ | |
server <-- db: 該当ユーザー | |
note over server | |
AuthorizationヘッダーとProtectSecretが等しいことを検証 | |
end note | |
server -> db: Diagnosisテーブルにdiagnosisを追加\ntimestamp\nUserUuid\nkeys | |
server <-- db | |
server -> db: Tekテーブルにkeyを追加 | |
server <-- db | |
app <-- server: JSON応答 | |
user <-- app: 診断結果の提出\n完了しました | |
user -> app: OK | |
user <-- app: ホームページに戻る | |
== バッチ - 追加 == | |
server -> db: Tekテーブルから14日前までのTEKかつexport前を取得 | |
server <-- db: TEK[] | |
note over server | |
TEKをGroupBy | |
GetRollingStartUnixTimeSecondsおよび | |
GetRollingPeriodSeconds | |
Regionsごとに処理 | |
TEKの順番を並べ替え | |
Security considerations: Random Order TemporaryExposureKey | |
zipの作成 | |
binとsigのJSON | |
bin: TEKのリスト | |
Keys | |
BatchNum | |
BatchSize | |
Region | |
StartTimestamp | |
EndTimestamp | |
SignatureInfos | |
sig: signature | |
binの署名 | |
sigの実装がおそらく秘密情報? | |
end note | |
server -> db: TEKのExport情報を追加 | |
== バッチ - 削除 == | |
server -> db: GetOutOfTimeKeysAsync | |
server <-- db: 14日前のTEKを応答 | |
server -> server: zipファイルを削除 | |
server -> db: TEKのExport情報を更新\n削除済みとして | |
server -> db: TEKリストから該当TEKを削除 | |
@enduml |