本番データ(DB+アップロード画像)のlocalhost限定バックアップ/リストア #25

Closed
opened 2026-09-27 14:03:01 +00:00 by joe · 5 comments
Owner

背景

本番用SQLite DBに葬儀情報が保存されている。DBだけでなく、DBから参照する領収書/見積/芳名録画像も含むバックアップと復元手段が必要。アプリは現状認証なしでLAN/Tailscaleから利用されるため、バックアップ取得・復元はlocalhostに限定する。

承認済み仕様

  • 設定画面から手動でZIPをダウンロード。ZIP内容はSQLiteの整合性あるスナップショット(sougi.db)とinstance/uploads/の画像
  • .envは含めない。DBにはカスタムOCRプロバイダのAPIキーが保存されるため、ダウンロードZIPが機密情報を含む警告を表示
  • 作成/復元のHTTP操作はlocalhostのみ許可し、LAN/Tailscale等のリモート要求は拒否
  • 復元は設定画面でZIPを検証・ステージし、明示確認後の次回アプリ起動時に適用(稼働中SQLiteファイルは置換しない)
  • 適用前に現在のDB+uploadsをロールバック用に退避。ZIPのメンバー/path traversal・SQLite integrityを検証し、失敗時は現データを維持
  • 復元待ちをキャンセルできる。復元機能は本番DBを置換するため、UIに対象ファイル/確認を明確に表示
  • 自動定期実行・.envバックアップ・別PCへの自動転送・アプリ内での即時リストアは対象外

受け入れ条件

  • 手動ダウンロードZIPにDBスナップショットとuploads画像があり、.envや任意ファイルは含まれない
  • localhost以外からバックアップ/復元endpointを呼べない
  • 不正/破損ZIPやSQLite integrity failureは拒否され、現DB/uploadsを変更しない
  • 復元は次回起動時のみ実行し、その前にロールバック用バックアップを作成
  • 通常利用と既存テストに影響しない
## 背景 本番用SQLite DBに葬儀情報が保存されている。DBだけでなく、DBから参照する領収書/見積/芳名録画像も含むバックアップと復元手段が必要。アプリは現状認証なしでLAN/Tailscaleから利用されるため、バックアップ取得・復元はlocalhostに限定する。 ## 承認済み仕様 - 設定画面から手動でZIPをダウンロード。ZIP内容はSQLiteの整合性あるスナップショット(`sougi.db`)と`instance/uploads/`の画像 - `.env`は含めない。DBにはカスタムOCRプロバイダのAPIキーが保存されるため、ダウンロードZIPが機密情報を含む警告を表示 - 作成/復元のHTTP操作はlocalhostのみ許可し、LAN/Tailscale等のリモート要求は拒否 - 復元は設定画面でZIPを検証・ステージし、明示確認後の**次回アプリ起動時**に適用(稼働中SQLiteファイルは置換しない) - 適用前に現在のDB+uploadsをロールバック用に退避。ZIPのメンバー/path traversal・SQLite integrityを検証し、失敗時は現データを維持 - 復元待ちをキャンセルできる。復元機能は本番DBを置換するため、UIに対象ファイル/確認を明確に表示 - 自動定期実行・`.env`バックアップ・別PCへの自動転送・アプリ内での即時リストアは対象外 ## 受け入れ条件 - 手動ダウンロードZIPにDBスナップショットとuploads画像があり、`.env`や任意ファイルは含まれない - localhost以外からバックアップ/復元endpointを呼べない - 不正/破損ZIPやSQLite integrity failureは拒否され、現DB/uploadsを変更しない - 復元は次回起動時のみ実行し、その前にロールバック用バックアップを作成 - 通常利用と既存テストに影響しない
Author
Owner

バックアップ/リストア仕様書を作成し、ブランチdocs/backup-restore-specへコミットしました(commit 217917f)。実装前のレビュー待ちです。

バックアップ/リストア仕様書を作成し、ブランチ`docs/backup-restore-spec`へコミットしました(commit `217917f`)。実装前のレビュー待ちです。
Author
Owner

承認済みバックアップ仕様から実装計画を作成しました。現在は実装前レビュー待ちです。テストでは常に一時DB/一時uploadsだけを使い、本番DBへの読み書きは行いません。

承認済みバックアップ仕様から実装計画を作成しました。現在は実装前レビュー待ちです。テストでは常に一時DB/一時uploadsだけを使い、本番DBへの読み書きは行いません。
Author
Owner

方針を簡素化しました。

  • バックアップ: 設定画面で予約→アプリ停止/再起動→起動前(HTTP受付前)にSQLite WAL checkpoint+DB/uploadsをZIP化→起動後にlocalhostでダウンロード。稼働中DBは読みません。
  • リストア: 設定画面でZIPを検証/予約→アプリ停止/再起動→起動前に現DB/uploadsをpre-restore.zipへ退避して置換。単一markerで失敗/途中停止を復旧。
  • 複雑なjournalやオンラインスナップショットは廃止。
    仕様書/計画を commit 5554e07 に反映済み。実装は未着手で、本番DBは開いていません。
方針を簡素化しました。 - バックアップ: 設定画面で予約→アプリ停止/再起動→起動前(HTTP受付前)にSQLite WAL checkpoint+DB/uploadsをZIP化→起動後にlocalhostでダウンロード。稼働中DBは読みません。 - リストア: 設定画面でZIPを検証/予約→アプリ停止/再起動→起動前に現DB/uploadsをpre-restore.zipへ退避して置換。単一markerで失敗/途中停止を復旧。 - 複雑なjournalやオンラインスナップショットは廃止。 仕様書/計画を commit `5554e07` に反映済み。実装は未着手で、本番DBは開いていません。
Author
Owner

実装完了(ブランチ feature/database-backup-restore → ローカルmainへマージ, commit b379e86)。

  • 設定画面に「バックアップを準備」→停止/再起動で起動前ZIP作成→/settings/backup/downloadでlocalhostダウンロード
  • 復元ZIPはRESTORE確認付きで予約→次回起動時に現DB/uploadsをpre-restore.zipへ退避して置換
  • 失敗/途中停止は単一markerで直前ZIPへ復旧、rollback ZIPもlocalhostで取得可
  • ZIPはDB+uploadsのみ、.env除外。loopback/同一origin以外は403
  • 全131テストパス(既存のgoogle-genai警告1件のみ)。実装中に本番DB/instanceは読み書きしていません。

リモートpushは未実施のため、このissueはpush時にクローズします。

実装完了(ブランチ `feature/database-backup-restore` → ローカルmainへマージ, commit `b379e86`)。 - 設定画面に「バックアップを準備」→停止/再起動で起動前ZIP作成→`/settings/backup/download`でlocalhostダウンロード - 復元ZIPは`RESTORE`確認付きで予約→次回起動時に現DB/uploadsを`pre-restore.zip`へ退避して置換 - 失敗/途中停止は単一markerで直前ZIPへ復旧、rollback ZIPもlocalhostで取得可 - ZIPはDB+uploadsのみ、`.env`除外。loopback/同一origin以外は403 - 全131テストパス(既存のgoogle-genai警告1件のみ)。実装中に本番DB/instanceは読み書きしていません。 リモートpushは未実施のため、このissueはpush時にクローズします。
Author
Owner

実装完了としてクローズします。設定画面からlocalhost限定でDB+uploadsのZIPを予約作成・ダウンロード、復元ZIPは検証して予約し次回起動時に退避ZIPを作って置換、失敗時は直前ZIPへ復旧します。ローカルmainへマージ済み(pushは未実施)。

実装完了としてクローズします。設定画面からlocalhost限定でDB+uploadsのZIPを予約作成・ダウンロード、復元ZIPは検証して予約し次回起動時に退避ZIPを作って置換、失敗時は直前ZIPへ復旧します。ローカルmainへマージ済み(pushは未実施)。
joe closed this issue 2026-09-27 16:57:35 +00:00
Sign in to join this conversation.
No labels
bug
cleanup
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
joe/sougi#25
No description provided.