# 開発ガイド

> HTML: https://remote.ivjn.us/docs/ja/development/

このドキュメントでは、このリポジトリでのビルド、テスト、ローカルでの exchange の起動方法を説明します。デプロイ手順、プロトコルのフィールド一覧、各プラットフォームのインストール詳細は、末尾のリンクにある各トピックのドキュメントを参照してください。

## ツールチェーン

ワークスペースは Rust 2021 を使用し、**Rust 1.88 以降**が必要です。バージョンはリポジトリルートの `Cargo.toml` の `rust-version` フィールドに記載されています。

## ワークスペースとバイナリ

Rust ワークスペースは 9 メンバーで構成されます。8 つは `crates/`、拡張 SDK は `sdk/extend/rust` にあります。プロトコル型は `crates/proto` だけで定義し、`exchange`、`agent`、`cli` はすべてこの crate に依存します。各クライアントにメッセージ構造体を複製しないでください。

| crate | パス | 生成物 |
|---|---|---|
| `proto` | `crates/proto` | ライブラリ。制御メッセージ、バイナリフレーム、共有データ構造はここだけに定義 |
| `exchange` | `crates/exchange` | バイナリ `exchange`（パッケージ名とバイナリ名は同一） |
| `agent` | `crates/agent` | バイナリ `remote-agent` |
| `cli` | `crates/cli` | バイナリ `remote-cli` |
| `updater` | `crates/updater` | `remote-agent` と `remote-cli` の自己更新用ライブラリ |
| `telemetry` | `crates/telemetry` | 3 者共通の例外・ログ報告ライブラリ |
| `tls-client` | `crates/tls-client` | 共通の rustls クライアント TLS ポリシーと任意のプロキシ接続のライブラリ |
| `worker-proto` | `crates/worker-proto` | Workers Exchange のプロトコル検証と認証情報ハッシュのライブラリ |
| `remote-extend-sdk` | `sdk/extend/rust` | 拡張 provider のフレーミングと契約のライブラリ |

`exchange` のエントリーポイントは `crates/exchange/src/main.rs` です。独立した `[[bin]]` テーブルがないため、`cargo build -p exchange` で生成されるのは `exchange` です。`agent` と `cli` はそれぞれの `Cargo.toml` でバイナリ名を `remote-agent` と `remote-cli` に設定しています。

接続テーブルは役割別に分割されています。

- `crates/exchange/src/hub.rs`: オンラインデバイス、再接続による置き換え、epoch
- `crates/exchange/src/hub/session_table.rs`: オペレーター側番号とデバイス側番号の変換
- `crates/exchange/src/hub/outbound.rs`: 接続ごとの上限付き送信キュー

## ビルド

リポジトリのルートで実行します。

リリースプロファイル（`opt-level = 2`、thin LTO、unwind を維持）は、サーバー、CLI、agent を生成します。

```bash
cargo build --release
```

バイナリは次の場所にあります。

- `target/release/exchange`
- `target/release/remote-cli`
- `target/release/remote-agent`

`release` が unwind を維持するのは、exchange が複数接続を処理する常駐プロセスだからです。1 つの接続タスクが panic しても、unwind により tokio はそのタスクだけを停止でき、同じプロセス内の他のデバイスのセッションまで終了させずに済みます。

デバイス側にはサイズ優先の profile（`opt-level = "z"`、LTO、`panic = "abort"`、`strip`、`codegen-units = 1`）もあります。

```bash
cargo build -p agent --no-default-features --profile release-small
```

生成物は `target/release-small/remote-agent` です。agent がクラッシュしても procd、systemd、またはスケジュールタスクが再起動するため、ここでは `panic = "abort"` によってサイズを削減できます。

ビルドにデータベースは必要ありません。`crates/exchange/src/db.rs` は sqlx の実行時クエリを使用し、`query!` マクロを使わないため、データベースなしで `cargo build` を実行できます。

## テスト

```bash
cargo test --workspace
```

Windows では Unix の `/bin/sh`（OpenWrt では `/bin/ash`）や PTY に依存するテストは実行しません。`crates/agent/src/pty.rs` のテストモジュールは `#[cfg(all(test, unix))]` で囲まれており、非 Unix プラットフォームではコンパイルされません。PTY 実装は `/bin/ash`、`/bin/sh` の順に試します。`exec.rs` のプロセスグループと Unix シグナルの処理も Unix でのみコンパイルされます。Windows のコマンドテストは PowerShell を使い、`/bin/sh` を呼びません。`exec.rs` や `pty.rs` の Unix 処理を変更した場合は、Linux でも `cargo test --workspace` を実行してください。Windows の結果だけでは不十分です。

crate 単位で範囲を絞ることもできます。例: `cargo test -p proto`、`cargo test -p exchange -- hub::`。

## ローカルで exchange を起動する

PostgreSQL を用意して、接続文字列を `DATABASE_URL` に設定します。この変数は `exchange` の `--database-url` に対応します（`crates/exchange/src/config.rs` 参照）。起動時に `db::connect` はコンパイル時に埋め込まれたマイグレーションを実行します。

```rust
sqlx::migrate!("../../migrations")
```

マイグレーションファイルはリポジトリルートの `migrations/` にあり、起動時に自動実行されます。sqlx-cli は不要です。

監査操作には監査暗号化キーも必要です。以下の例はローカルテスト用のキーを生成します。安全に保存し、次回以降の起動でも同じキーを使用してください。毎回生成し直すと、既存の監査詳細を復号できなくなります。

```bash
export DATABASE_URL='postgres://luci:luci@127.0.0.1:5432/luci'
export AUDIT_ENCRYPTION_KEY="$(python -c 'import base64, secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())')"
cargo run -p exchange -- --listen 127.0.0.1:8080
```

PowerShell では、先に環境変数を設定してから起動します。

```powershell
$env:DATABASE_URL = "postgres://luci:luci@127.0.0.1:5432/luci"
$env:AUDIT_ENCRYPTION_KEY = python -c "import base64, secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())"
cargo run -p exchange -- --listen 127.0.0.1:8080
```

リリースバイナリをビルド済みなら、上記の `cargo run -p exchange --` を `./target/release/exchange` に置き換えられます。既定の待受アドレスは `0.0.0.0:8080` です。ローカルデバッグでは明示的に `127.0.0.1` にバインドすることを推奨します。

有効な運用アカウントがデータベースに 1 つもない場合、起動時に管理者を自動作成し、その回の起動ログにトークンを出力します。平文が表示されるのはこの一度だけです。デプロイ、リバースプロキシ、アカウントの詳しい説明はリポジトリの `docs/deployment.md` にあります。このページはサーバーアドレスを含むため、本サイトでは公開していません。

## コミット前の検査

リポジトリのルートで以下を実行します。Rust の変更では対象 crate のテストから始め、その後ワークスペース全体を検査します。書式検査で無関係な既存の差分が見つかった場合は、変更ファイルだけを整形してください。Android、ブラウザー拡張、モバイルコンソールにはそれぞれのビルドとテストも必要で、Rust テストだけでは検証できません。

```sh
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
```

## ドキュメントの保守

実装の動作を確認してから `docs/` のガイドを更新します。Web サイトの記事には `website/docs/<topic>.md` の参照ソースと、`website/docs/content/<locale>/<topic>.md` の 9 言語の本文があります。コマンド、フィールド、コード例、見出し階層を一致させてください。HTML だけを手編集せず、スクリプトでページと検索索引を生成します。Python 3.11+、markdown-it-py、Node.js を用意し、リポジトリのルートで実行してください：

```sh
python -m pip install markdown-it-py
python scripts/build-docs.py
python scripts/build-docs.py --check
python scripts/test-docs.py
python scripts/test-docs-markdown.py
node scripts/test-docs-locale.js
python scripts/test-build-docs.py
python scripts/test-site-seo.py
```

生成チェックでは全生成ファイルをバイト単位で比較し、欠落や古い出力があれば、ファイルを書き込まずに失敗します。CI は再生成の前にこのチェックを実行します。

検査は翻訳の完全性、コード例、見出し構造、ページリンク、アンカー、言語ルーティングを確認します。生成ページはソースと一緒にコミットしてください。ドキュメントのビルドはローカルファイルの更新であり、サイトのデプロイとダウンロードの公開は別の操作です。

## 関連ドキュメント

- [技術ガイド](/docs/ja/architecture.md) — 外向き接続、セッション変換、epoch、上限付きキュー、トークン保存
- [使用方法](/docs/ja/getting-started.md) — ログイン、デバイス追加、agent 起動、コマンド実行、シェル接続
- デプロイガイドはリポジトリの `docs/deployment.md`（サーバーアドレスを含むため、本サイトでは非公開）
- [通信プロトコル](/docs/ja/websocket-protocol.md)
- [マルチプラットフォームへのデバイス展開](/docs/ja/platform-installation.md)
