Memories / ドキュメント

このページの内容

Memories

Memories の Android/iOS クライアントです。Flutter UI は crates/ffi/memories.h を通じて共有 Rust サービスを呼び出します。独立したストレージや暗号プロトコルを実装しません。

モードを選ぶ

初回起動時には、モード設定のないバージョンからアップグレードした後の初回起動も含め、作業する場所を選びます。

モード データの場所 必要なもの
Standalone この電話上の暗号化ライブラリ。オフラインで動作 ローカルライブラリを作成するか、既存のものを解除
Center 自分のセルフホストサーバーのホストストア https://center.example.com などのサーバーオリジンとメンバートークン
SaaS https://memories.ivjn.us のホストストア このサービスのメンバートークン。URL は固定

アプリの Center モードは、ホストストレージを有効にして稼働するサーバー(memories-center --data DIR)を意味します。ローカルデバイスに署名済みチケットを配布する、チケット専用の認可 Center とは異なります。Center と SaaS は同じホストクライアントを使い、エンドポイントの選択と保存される接続プロファイルが異なります。どちらも、先にローカルライブラリを作成または解除する必要はありません。

初回接続

  1. モードを選びます。アプリは次回起動用に選択を記憶します。
  2. Standalone ではライブラリを作成または解除します。Center では API パスを含めずにサーバーの HTTPS オリジンを入力します。SaaS では固定のサービスアドレスを使います。
  3. どちらのホストモードでも、サービス運用者から提供されたメンバートークンを入力し、接続を選びます。メンバーのロールとスコープによって実行できる操作が決まります。コンテンツの操作には、運用者の管理トークンではなくメンバートークンを使ってください。
  4. 接続後、ホスト型ナレッジを開いてナレッジの閲覧、検索、表示、編集、削除を行います。リクエストの確認やペアリング済みデバイスを開くこともできます。サーバーアドレス、現在の保管庫、付与されたスコープは常に表示されます。

ホストコンテンツは、運用者が保持するパスワードで保存時に暗号化されますが、運用者は内容を読むことができます。アプリはサーバーは読み取り可能と表示します。デバイス間の封印されたシークレットには、別のエンドツーエンド保護境界があります。

切り替え、切断、再接続

ログイン前後にメインツールバーのモードを切り替えを使います。ダイアログは現在のモードを示し、影響を説明します。別のモードを選ぶと切り替わり、キャンセルを選ぶとセッションを維持します。先に開いているエディターを完了するか閉じてください。未保存の下書きを離れる場合は確認を求めます。

操作 結果
モードを切り替える ローカルライブラリをロックし、共有を停止し、アクティブなホスト接続を閉じて表示中のコンテンツを消去。新しいモードを保存
Standalone に戻る ローカルライブラリ画面をロック状態で再表示。既存データは保持
Center または SaaS に再度入る 利用可能な場合、そのモードの保存済み接続を復元
切断する 現在のプロファイルの保存済みトークンを削除し、セッションを閉じる。URL と他のモードのプロファイルは保持
アプリをバックグラウンドに移す ローカルアクセスをロックし、ホストセッションを消去し、機密ページと下書きを閉じる
バックグラウンドから戻る ホストページで保存済みセッションに再接続を使うか、トークンを入力して再接続

切り替えはライブラリデータのアップロード、コピー、マージ、削除を行いません。切断してもサーバー上のトークンは失効しません。Center と SaaS は、URL/トークンの組を別々のプラットフォームセキュアストレージ項目に保存します。アップグレード時には、古いホスト接続を対応するモードにだけインポートします。設定と移行を参照してください。

利用可能な機能

ワークフロー Standalone Center / SaaS
ローカルライブラリの作成、バックアップ、復元 利用可能 ホストサービスを使用。ローカル設定は不要
ナレッジの閲覧、検索、表示、編集、削除 解除後に利用可能 ホスト型ナレッジ。操作はトークンスコープで制限
ナレッジカードの作成 ローカルの全画面エディター ホスト API が受け付けるフィールドを備えたホスト型全画面エディター
ホスト認可リクエストの確認 Center または SaaS に切り替え 保留/履歴タブ、承認/拒否の確認、更新
デバイスのペアリング ローカルのデバイス/メンバー承認ワークフロー 権限に応じたホスト型ペアリング、封印シークレット、デバイス操作
リレー共有とクラウド接続 ローカルライブラリの操作から利用可能 ホストページには公開されない

ホスト型の作成ではタグ、ソース、関係を省略します。既存の通常カードの編集はこれらのフィールドに対応し、他のメタデータを保持します。通常のメモリはテキストエディターを使います。構造化プロファイル、保護カード、型テンプレート、E2E カードは、この汎用エディターでは表示のみです。どちらのエディターも保存に失敗すると下書きを保持します。下書きはアプリのロックやバックグラウンド移行を越えて永続化されません。コンテンツ編集と認可を参照してください。

接続のトラブルシューティング

アプリは書き込み専用アカウントも含め、接続を保存する前に /v1/session でトークンを検証します。セルフホストサーバーはアプリと一緒にアップグレードしてください。読み取り専用アカウントは変更操作なしで閲覧でき、書き込み専用アカウントはライブラリや型リストを読み込まずに作成できます。サーバーはすべての操作を改めて認可します。検索はプライベートコンテンツ、認証情報、ファイルを除外します。クエリを消去するとナレッジ一覧に戻ります。期限切れまたは失効済みセッション、権限不足、利用できないサーバーには、ローカライズされたエラーを表示します。401 の場合は切断し、有効なトークンで接続し直す必要があります。

  • 接続できない: 完全な HTTPS オリジン、ネットワーク、証明書、トークンを確認してください。セルフホスト Center はホストストレージを有効にする必要があります。チケット専用サービスはこの画面を提供できません。電話上の localhost は電話自身です。
  • 権限が拒否される: トークンの保管庫、ロール、スコープ、有効期限をサービス運用者に確認してください。別のモードを選んでもアクセス権は得られません。
  • 保留中のリクエストがない: 更新し、要求者/保管庫/承認者の振り分けを確認してください。履歴タブは完全なサーバー監査ログではありません。
  • バックグラウンド移行後にセッションが閉じた: 明示的に再接続してください。未保存の下書きはロックの一環として破棄され、復元できません。
  • ネイティブサービスを開始できない: 対応する Rust ライブラリを含むビルドを使ってください。ホストモードも FFI を使うため、ネイティブライブラリが必要です。

開発

リポジトリルートから scripts/build-android.ps1 または scripts/build-ios.sh を使い、先にネイティブライブラリをビルドしてください。ツールチェーン要件と署名手順は、ルートの README を参照してください。

CI と同じ Flutter 3.44.2 を使います。このディレクトリから実行してください。

flutter pub get
flutter gen-l10n
dart format --output=none --set-exit-if-changed lib test integration_test
flutter analyze
flutter test
flutter test integration_test/native_smoke_test.dart -d DEVICE_ID
flutter run -d DEVICE_ID

ウィジェットテストは偽のバックエンドを使い、ロック画面のライフサイクル、モード選択と切り替え、ホストセッションの分離、カード、ローカライズ、シークレット参照フローを検証します。クリップボードテストは Flutter のプラットフォームチャネルをモックし、OS クリップボードへの配信は検証しません。統合テストは実際のネイティブライブラリを読み込み、デバイス上に使い捨てデータベースを作成します。通常の実行はプラットフォームのアプリケーションサポートディレクトリと、Keychain/Keystore で保護されたローカル要素を使います。開発中はテストデータを使ってください。現在の信頼境界は SECURITY.md を参照してください。

文書のシークレットとクリップボード

Standalone モードで、メモリまたはカードのメニューを開き、文書内のシークレットを保護を選ぶと、現在の本文中の完全一致する値を名前付き参照に置き換えます。履歴に関する警告を確認し、参照名と非表示のシークレットを入力して、求められたら認可してください。Rust サービスは、認証情報の保存と本文の置換を単一トランザクションで行います。

文書、保護カード、認証情報でシークレットをコピーを選ぶと、確認と認可の後に現在の値をコピーします。文書では先に参照選択を表示します。OTP カードはシードをコピーします。別の OTP 操作はワンタイムコードを生成します。値は表示されず、バックグラウンド移行やロック後に届く遅延応答は破棄されます。完了したクリップボードコピーは、ロック後も残る場合があります。

通常の編集は参照マッピングを保持します。古い文書バージョンと既存のバックアップは以前の内容を保持します。参照の規則、更新、互換性、クリップボードの制限は wiki シークレットガイドを参照してください。これらの操作を追加するときは、Flutter アプリと一緒にネイティブライブラリを再ビルドしてください。

ローカライズ

アプリバーの言語アイコンから、英語、簡体字中国語、日本語、ドイツ語、フランス語、システム既定を選べます。この設定は暗号化ライブラリとは別に保存され、ロック中も利用できます。言語を切り替えても現在のライブラリセッションは維持されます。

翻訳は lib/l10n/app_*.arb にあり、flutter gen-l10n が Git の対象外の lib/l10n/generated/ ディレクトリを生成します。Material と Cupertino のコントロールは Flutter のローカライズデリゲートを使います。メッセージや言語を追加するときはローカライズガイドに従ってください。

セッション共有(リレー RPC ホスト)

Standalone モードで、解除済みかつフォアグラウンドの間、オーバーフローメニューにセッションを共有が表示されます。 高エントロピーのトークンを使って wss://…/v1/rpc/{room}/a に参加し、デスクトップ CLI がスロット b として接続できます(MEMORIES_DAEMON_RELAY / MEMORIES_DAEMON_ROOM / MEMORIES_DAEMON_TOKEN)。バックグラウンド移行やロックでセッションを停止します。MVP のモバイルには HTTP/WS 待ち受けはなく、ネイティブ FFI の拒否リストは引き続き適用されます。リモートデーモンを参照してください。

生体認証による解除と機密操作

解除済みの Standalone ライブラリで、オーバーフローメニュー → 生体認証 / デバイスロックで解除を使います(既定ではオフ。有効化には一度のシステム確認が必要です)。lib/biometric.dart は local_auth をラップします(Android ではデバイスの PIN/パターン/パスワードへのフォールバックを備えた BiometricPrompt、iOS では Face ID / Touch ID と NSFaceIDUsageDescription を Info.plist 内に設定)。MainActivity は FlutterFragmentActivity を継承し、local_auth の要件を満たします。

  • クイック解除用のライブラリパスワードは AndroidOptions.biometric(resetOnError: false) で保存されます。Android Keystore の AES 鍵には setUserAuthenticationRequired(true) と setInvalidatedByBiometricEnrollment(true) を設定します。iOS の Keychain 項目は KeychainAccessibility.passcode を使います。
  • 認証ゲートの対象: ライブラリの解除、認証情報平文のコピーと表示、保護カード / OTP の使用、ペアリングと Hosted Center リクエストの承認、封印と再封印。
  • 生体認証登録が変わった場合(KeyPermanentlyInvalidatedException)、アプリは利用者に通知し、デバイス認証情報で再検証します。古いクイック解除用コピーだけを破棄し、一度パスワードで解除した後に鍵を再作成します。ライブラリは消去しません。
  • 生体認証/デバイス認証情報がない場合、または設定がオフの場合: 既存のパスワードフローを使います。
  • テストは DeviceAuth / UnlockSecretStore をモックします(test/biometric_test.dart)。

コンテンツエディター

lib/content_editor.dart は、新規メモリ、認証情報、Hosted Center エントリーで共有されます。ファイルインポート(タイトルはファイル名から取得)、.env のような内容向けの等幅モード(自動検出または切り替え)、ファイル名または最初の空でない行から推測するコンテンツ優先の名前に対応し、保存時にまだ空の場合だけ名前の入力を求めます。手書き(ペン/消しゴム/元に戻す/消去、ML Kit Digital Ink)と OCR(カメラ/写真/ファイル、ML Kit テキスト認識)はデバイス上で実行されます。手書きと OCR を参照してください。ウィジェットテストは ScanServices の偽物を注入します。

メモリとナレッジカードは保存が成功するまで開いたままです。書き込みに失敗しても下書きを保持し、再試行できます。変更した状態で離れるときは確認を求めます。下書きはメモリ内にのみ保持され、バックグラウンド移行やアイドルロックでは破棄されます。ファイルインポートは既存テキストを置き換える前に確認します。メモリは保存前にプライベート/通常の設定を表示し、添付ファイルの再試行では現在の編集中に保存済みのファイルをスキップします。

ナレッジカードは、常時表示の保存操作、カスタムフィールド、タグ、ソース、関係を備えた全画面エディターを使います。コンテンツを編集は、ファイルインポート、手書き、OCR 用の共有テキストエディターを開きます。ホスト型の作成は、既存のモバイル API が受け付けるメタデータだけを公開します。

モバイルでの認可

Center と SaaS のページは、保留中のリクエストと履歴を分けます。承認または拒否を確定する前に、要求者、保管庫、アクセススコープ、期間、理由全文を確認してください。承認は引き続き既存のデバイス認証ゲートを使い、要求者は別途権限付与を受け取る必要があります。エラー時は再試行用にリクエストを保持します。下に引いて更新するか、更新ボタンを使ってください。

Center のリクエスト API は完全な決定履歴を返しません。履歴タブは、現在の接続中に行われた決定と、Center が返した承認済みリクエストを組み合わせます。これらのローカル記録はページを離れると消去されます。新しい接続に失敗した場合は、保存済みプロファイルを置き換えずにその接続を閉じます。

ローカルのメンバー管理は、表示されたロールで許可される操作だけを示します。確認画面はメンバーと変更前後のアクセス権を明示します。Rust サービスは現在のポリシーを再確認します。UI のフィルタリングが権限を付与することはありません。Owner のメンバーシップは通常のロール操作では変更できず、所有権移転は Owner にだけ表示されます。

ブランド

ロゴのソース: assets/brand/logo.svg(+ logo-mono.svg、アダプティブ用 logo-foreground.svg)。アイコンとスプラッシュ画像は rsvg-convert で描画されました。ロゴ変更時には同じサイズで再生成してください。