Memories / ドキュメント

このページの内容

OneDrive と Google Drive の認可

CLI はブラウザーでのログイン、暗号化されたローカルアカウントの保存、ステータス、ローカルログアウト、および OneDrive または Google Drive のアプリケーションフォルダーを介した不変の暗号文オブジェクトの cloud sync をサポートします。トークンの更新結果は、その後のアップロードより前に永続化されます。実際のアカウントでの検証はまだ完了していません。各デバイスではプロバイダーごとに 1 つのアカウントを接続できます。再ログイン時は、新しい認可が成功してから、そのプロバイダーのアカウントだけを置き換えます。

ログイン前の準備

新しい CLI をビルドまたはインストールし、同じ新しいバージョンでデーモンを再起動します。

cargo install --path crates/cli --locked
memories daemon

デーモンは別のターミナルで実行してください。ログインを実行するターミナルでは、必要に応じて既存のライブラリのロックを解除し、memories sudo を実行します。すべてのコマンドで同じ --home/MEMORIES_HOME を使用してください。新しいライブラリには、まず memories init が必要です。そのデータベースをクラウド同期ディレクトリに移動しないでください。

OAuth アプリケーション登録は同梱されていません。独自の登録を使用してください。CLI が Microsoft または Google アカウントのパスワードを要求することはありません。認証と同意は、ブラウザーでプロバイダーの Web サイト上で行います。

OneDrive の登録

  1. Microsoft Entra ID でアプリ登録を作成します。ビジネス用と個人用の OneDrive の両方が必要な場合は、任意の組織ディレクトリのアカウントおよび個人用 Microsoft アカウントのサポートを選択します。このクライアントは common テナントを使用します。
  2. 認証で モバイルとデスクトップ アプリケーションのプラットフォームを追加し、リダイレクト URI を http://localhost/oauth/callback に設定します。これはパブリックデスクトップクライアントであり、Web または SPA アプリケーションではありません。このフロー用のクライアントシークレットを作成しないでください。
  3. 委任された Microsoft Graph のアクセス許可 User.Read と Files.ReadWrite.AppFolder を構成します。ログインでは offline_access も要求します。組織の同意ポリシーによっては管理者の承認が必要です。
  4. アプリケーション(クライアント)ID をコピーし、次を実行します。
memories sudo
memories cloud login onedrive --client-id YOUR_MICROSOFT_CLIENT_ID

コールバックは http://localhost:PORT/oauth/callback を使用します。Microsoft は localhost リダイレクト URI の照合でポートを無視します。パスは登録と一致する必要があります。リスナーは IPv4 ループバックだけにバインドします。オプションの --port PORT で固定ポートを選択できます。指定しない場合は OS が空いているポートを選びます。

代わりに、--client-config PATH は client_id を含む JSON オブジェクトを受け付けます。カスタムの認可 URL、トークン URL、および機密クライアントのシークレットは受け付けません。

Google Drive の登録

  1. Google Cloud プロジェクトを作成または選択し、Google Drive API を有効にします。
  2. OAuth 同意画面を構成します。アプリがテストモードの場合は、Google アカウントをテストユーザーとして追加します。drive.appdata に加え、アカウント識別用の openid、email、profile を要求します。
  3. 種類が デスクトップ アプリの OAuth クライアントを作成し、その JSON ファイルをダウンロードします。CLI が想定するのはダウンロードした installed セクションであり、Web クライアントの構成ではありません。
  4. JSON をこのリポジトリの外に保管し、次を実行します。
memories sudo
memories cloud login google-drive --client-config /path/to/google-desktop-client.json

Windows CMD の例:

memories cloud login google-drive --client-config "%USERPROFILE%\Downloads\google-desktop-client.json"

コールバックは http://127.0.0.1:PORT/oauth/callback を使用します。デスクトップアプリケーションのフローはループバックコールバックをサポートするため、ホストされたコールバックサーバーは不要です。ダウンロードしたエンドポイントのフィールドは無視され、クライアントは固定の Google 公式エンドポイントを使用します。installed-app のクライアントシークレットが指定されている場合は JSON から読み取り、コマンド引数からは読み取りません。デスクトップアプリのシークレットは PKCE の代わりにはなりません。

Google はテストモードのアプリケーションのリフレッシュトークンを失効させることがあります(基本以外のスコープを要求する場合、通常は 7 日後です)。必要になったら再認可してください。公開およびプロバイダーによる検証の要件はアプリケーションによって異なります。

ステータス、キャンセル、ログアウト

memories cloud status
memories cloud sync onedrive
memories cloud sync google-drive
memories sudo
memories cloud logout onedrive
memories cloud logout google-drive

ステータスは、プロバイダー、アカウントの識別情報、表示名またはメールアドレス、アクセストークンの有効期限、リフレッシュトークンが保存されているかどうかを返します。アクセストークン、リフレッシュトークン、クライアントシークレットは返しません。sync_enabled は、少なくとも 1 つのクラウドアカウントが接続されていることを示します。object_sync は outbox/inbox の件数だけを報告します。cloud sync は必要に応じてプロバイダーとの転送前にトークンを更新します。アクセストークンが期限切れであることだけでは、プロバイダーへの同意が取り消されたとは限りません。 有効期限は、トークン交換の開始時点から保守的に測定します。ネットワーク応答やアカウントプロフィールの問い合わせが遅くても、トークンの有効期間は延長されません。

ログアウトはローカルアカウントを削除し、そのプロバイダーの保留中のログインをキャンセルします。Microsoft または Google のサーバー上の同意は取り消しません。リモートでの取り消しには、プロバイダーの接続済みアプリの設定を使用してください。ローカルレコードを削除しても、ストレージのスナップショットや古いローカルコピーからのフォレンジック上の消去は保証されません。

ログインには 5 分の制限があります。--no-browser はブラウザーを開かずに認可 URL を表示しますが、このコンピューターでのコールバックを引き続き待ちます。これは帯域外または手動コードのフローではなく、リモートまたはヘッドレスのログイン機構でもありません。 タイムアウトまたは通常のエラー時には、CLI は保留中のチケットをキャンセルします。CLI を強制終了した場合は、有効期限まで待つか、再試行前に cloud logout PROVIDER を使用してください。

セキュリティとライフサイクル

  • OAuth は S256 PKCE と予測不能な state 値を伴う認可コードを使用します。コールバックのメソッド、Host、オリジン、パス、重複フィールド、state、有効期限、リプレイを確認します。プロバイダーのエラーとコールバックページはコードやトークンをそのまま表示しません。
  • ブラウザーの待機、トークン交換、識別情報の問い合わせは、デーモンの mutex とデータベーストランザクションの外で CLI プロセス内で実行します。HTTPS リクエストはタイムアウトと応答サイズに上限を設け、自動リダイレクトを無効にし、環境のプロキシを継承しません。この初期トランスポート構成では、プロキシを必要とするネットワーク環境はサポートされません。
  • デーモンは、プロバイダー、クライアント ID、ローカル呼び出し元に結び付けた短命のチケットを発行します。保存には再度 sudo が必要です。ロック、再起動、ログアウトは保留中のチケットを無効にします。遅れて届いた HTTP 結果で、キャンセル済みのログインを復元することはできません。
  • ローカル CLI はプロバイダーとの交換を実行する信頼済みの主体です。サービスのトークン書き込み操作には有効なチケットと権限昇格が必要です。これはリモートエンドポイントではなく、MCP から使用できません。トークン読み取りコマンドはありません。
  • アカウントとトークンは暗号化されたローカル状態の中にあります。エクスポートされたバックアップ、デバイス承認、vault 同期、監査出力、MCP から除外されます。各デバイスで個別にログインする必要があります。クラウドログインで vault のメンバー資格は付与されません。
  • 所有するシークレットバッファーはゼロ化します。HTTP/URL/JSON ライブラリや OS メモリに一時的なコピーが残る可能性があります。詳細は SECURITY.md を参照してください。

この状態フィールドは、存在しない場合の後方互換性があります。認可済みのストアを古いデーモンで再度開いて書き直さないでください。古いデーモンはクラウドアカウントを理解せず、新しいフィールドを破棄して、再度のクラウドログインが必要になる可能性があります。

検証の範囲

テストでは、ローカル HTTP フィクスチャに対する両プロバイダーの交換、実際のループバックコールバック、暗号化された永続化、呼び出し元への結び付け、リプレイ、ロック後のキャンセル、スコープまたはリフレッシュトークンの不足、エラーの秘匿、バックアップからの除外、MCP の拒否を確認します。テスト用トランスポートはモジュール内で非公開です。本番エンドポイントは固定の HTTPS です。

実際のアカウントの認可には、登録済みのクライアント ID または構成と、ユーザーの同意が必要です。このテストなしに実際のプロバイダーアカウントを検証済みと主張することはありません。モバイルは後述のネイティブ認可フローを使用します。実際の同意はまだ検証されていません。

2026-09-09 に確認した参考資料:

モバイルクライアント

クラウドボタンは、接続ステータス、接続または再接続、今すぐ同期、切断を開きます。同期はフォアグラウンドでのみ行います。AppAuth はシステムブラウザーを開き、state を検証し、PKCE を生成します。ブラウザーによってアプリがバックグラウンドになると、ライブラリがロックされます。戻ったら、Rust がコードを交換する前にロックを解除し、再度ローカルで認可してください。アクセストークンとリフレッシュトークンは Rust が検証および保存し、Dart には返しません。

プラットフォーム固有のパブリッククライアント登録を使用してビルドします。

  • --dart-define=MEMORIES_ONEDRIVE_CLIENT_ID=...
  • --dart-define=MEMORIES_ONEDRIVE_REDIRECT_URI=app.memories.memories:/oauth/callback
  • --dart-define=MEMORIES_GOOGLE_CLIENT_ID=...
  • --dart-define=MEMORIES_GOOGLE_REDIRECT_URI=...

クライアント ID が未設定の場合は、説明メッセージを表示してログインを無効にします。Web クライアントシークレットを埋め込んだり、デスクトップのループバック構成を再利用したりしないでください。プラットフォーム、バンドルまたはパッケージ、署名 ID に対してプロバイダーがサポートする正確なネイティブリダイレクトを使用してください。Google の iOS 登録では一般にクライアント ID を逆順にしたスキームを使用します。Google の Android 登録とリダイレクトの制限は異なるため、Android ビルドを配布する前に、プロバイダーがサポートするネイティブフローで検証する必要があります。URI が設定されていることだけでは、プロバイダーの同意がサポートされる証拠にはなりません。

既定の登録済みアプリスキームは app.memories.memories です。別のカスタムスキームを使う場合、Android は Gradle プロパティ memoriesOAuthScheme(例えば ORG_GRADLE_PROJECT_memoriesOAuthScheme を通じて)を受け付けます。iOS は MEMORIES_OAUTH_SCHEME を mobile/ios/Flutter/Memories.xcconfig 内で使用します。スキームはネイティブコールバック登録と Dart のリダイレクト URI に一致する必要があります。両プロバイダーを有効にする場合は、互換性のあるコールバックを登録するか、2 番目のスキームをネイティブのマニフェストまたは URL types に追加してください。HTTPS のアプリリンクまたはユニバーサルリンクには、プラットフォームの関連付けファイルとネイティブ構成が必要です。既定のカスタムスキームビルドでは有効になりません。

ブラウザーログインが完了しても、古い権限昇格セッションは復元できません。ローカルのパスワードプロンプトをキャンセルしても、クラウド認可は変わりません。ロックまたはバックグラウンド移行は、遅れて届いた同期結果の適用をキャンセルします。ネットワーク障害時は、後の「今すぐ同期」に備えてキューのデータを保持します。UI は完了した操作と、保留作業が残る制限付きの実行を区別します。サインアウトはローカルトークンを削除しますが、プロバイダーの同意やクラウドファイルは削除しません。実際のプロバイダーの検証については、リリース条件を参照してください。