背景
現在、接続プロファイルは AsyncStorage に平文で保存されている。将来 Sentry 等のクラッシュレポーターを導入した場合、ナビゲーション URL に含まれる ip/token が外部サービスに送信されるリスクがある。
また、ターミナル画面で使えるコマンドスニペットの保存機能を将来追加する予定があるため、この機会に SQLite ベースの永続化基盤を整備する。
やること
1. パッケージ追加
```bash
npx expo install expo-sqlite expo-secure-store
```
2. DB クライアントの実装 (src/db/client.ts)
expo-secure-store でランダムな暗号化キーを生成・保管
expo-sqlite の useSQLCipher: true で DB を開く
- アプリ起動時に一度だけ初期化・マイグレーション実行
3. スキーマ
```sql
CREATE TABLE profiles (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
ip TEXT NOT NULL,
token TEXT NOT NULL,
last_connected_at TEXT
);
CREATE TABLE snippets (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
command TEXT NOT NULL,
created_at TEXT NOT NULL
);
```
snippets は全接続先共通(profile_id なし)
4. AsyncStorage からのデータ移行
- 初回起動時に
connectionProfiles キーのデータを SQLite に移行
- 移行完了後に AsyncStorage のエントリを削除
- 移行済みフラグを SecureStore に保存(二重移行防止)
5. ナビゲーション修正
ip/token を URL パラメータから除去
profileId のみ URL で渡し、各画面は DB から ip/token を取得
```
変更前: /session-picker?ip=100.x.x.x&token=uuid
変更後: /session-picker?profileId=abc123
```
6. ファイル構成
```
src/
└── db/
├── client.ts # DB 初期化・暗号化キー管理
├── profiles.ts # profiles テーブルの CRUD
└── snippets.ts # snippets テーブルの CRUD(スニペット実装時に追加)
```
注意点
expo-secure-store は iOS で 1 エントリあたり 2KB の上限があるが、暗号化キー(UUID)のみ保存するため問題なし
- SQLCipher のキーは SecureStore に保存するため、アンインストール時にキーも消える(データ復元不可)。これは意図した動作
- スニペット機能の UI 実装はこの Issue のスコープ外
関連
背景
現在、接続プロファイルは AsyncStorage に平文で保存されている。将来 Sentry 等のクラッシュレポーターを導入した場合、ナビゲーション URL に含まれる ip/token が外部サービスに送信されるリスクがある。
また、ターミナル画面で使えるコマンドスニペットの保存機能を将来追加する予定があるため、この機会に SQLite ベースの永続化基盤を整備する。
やること
1. パッケージ追加
```bash
npx expo install expo-sqlite expo-secure-store
```
2. DB クライアントの実装 (
src/db/client.ts)expo-secure-storeでランダムな暗号化キーを生成・保管expo-sqliteのuseSQLCipher: trueで DB を開く3. スキーマ
```sql
CREATE TABLE profiles (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
ip TEXT NOT NULL,
token TEXT NOT NULL,
last_connected_at TEXT
);
CREATE TABLE snippets (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
command TEXT NOT NULL,
created_at TEXT NOT NULL
);
```
snippetsは全接続先共通(profile_id なし)4. AsyncStorage からのデータ移行
connectionProfilesキーのデータを SQLite に移行5. ナビゲーション修正
ip/tokenを URL パラメータから除去profileIdのみ URL で渡し、各画面は DB から ip/token を取得```
変更前: /session-picker?ip=100.x.x.x&token=uuid
変更後: /session-picker?profileId=abc123
```
6. ファイル構成
```
src/
└── db/
├── client.ts # DB 初期化・暗号化キー管理
├── profiles.ts # profiles テーブルの CRUD
└── snippets.ts # snippets テーブルの CRUD(スニペット実装時に追加)
```
注意点
expo-secure-storeは iOS で 1 エントリあたり 2KB の上限があるが、暗号化キー(UUID)のみ保存するため問題なし関連