エンタープライズ — 登録とフリート
Bromure Agentic Coding が1台だけあるなら、それは個人向けのツールです。チーム全体では、管理者が組織的な問いに答える必要が生じることがよくあります。どの Mac がアプリを実行しているか、エージェントがどのパッケージを取り込んでいるか、トークンがどれだけ消費されているか、そしてプロンプトインジェクション検出器を作動させたワークスペースがあるか。Bromure Enterprise Manager(bromure.io 上のワークスペース)への登録は、登録された各 Mac からセッションメタデータ(プロンプトは決して含まず、シークレットも決して含まない)をストリーミングすることで、まさにそのフリートの可視性を提供します。
本章では、Mac の登録、そのアップロードを認証する mTLS アイデンティティ、正確に何がアップロードされ何がアップロードされないか、ワークスペースごとのオプトアウト、管理者のフリートビュー、リモートの同意処理、そしてオフボーディングについて説明します。ローカルトレース(登録が置き換えるものではない、Mac 上の監査証跡)は トレース で扱います。エンタープライズレポートに供給されるパッケージインベントリは サプライチェーン保護 です。
2つの独立したシステム
「フリート」という言葉は、区別しておく価値のある2つの機能にまたがっています。両者はトラストルートを共有していないためです。
- bromure.io 登録(本章)は、Mac をワークスペースに登録し、組織の CA によって発行された相互 TLS 証明書で認証して、セッションメタデータをクラウドにストリーミングします。
- リッチクライアント(リモートアクセス)は、1台の Mac が他の Mac の実行中インスタンスを SSH 経由でミラーリングできるようにし、SSH ホストキーと登録された公開鍵で認証します。
どちらも他方に依存しません。リッチクライアントを一切使わずに登録することも、どれも登録せずにホストをミラーリングすることも、両方行うこともできます。登録の mTLS スタックはフリートテレメトリ専用であり、リッチクライアントのミラーリングは SSH を信頼します。両者はこのバージョンでは意図的に統合されていません。
Bromure Enterprise Manager での登録
登録はコードベースです。管理者は bromure.io のユーザー詳細ページで、アプリ agentic-coding にスコープされた使い捨ての6単語登録コードを発行します。そのコードをアプリ(または CLI)に貼り付けると、Mac はワークスペースのインストールとして自身を登録します。
アプリから
- 管理者から6単語の登録コードを入手します。
- Bromure Agentic Coding(アプリ名メニュー)→ Enroll in bromure.io… を開きます。この項目は Check for Updates… のすぐ下にあります。bromure.io Enrollment というタイトルのウィンドウが開きます。
- コードを Enrollment Code フィールド(プレースホルダー:
six-word-enrollment-code)に貼り付けます。 - 必要に応じて Device Name を編集します(この Mac の名前がデフォルトになります。ヘルプテキスト: "Shown to your administrator so they can recognize this Mac.")。
- 必要に応じて Advanced を展開し、セルフホストまたはステージングサーバー用に Server URL (optional) を設定します。
- Enroll(Return)または Cancel(Esc)をクリックします。
このシートは、登録によって何が有効になるかを明確に述べています。登録すると「セッションメタデータ(ツール、ファイル、コマンド、トークン使用量)をワークスペースに送信し、管理者がアクティビティを確認できるようにします。プライベートモードのワークスペースは決してストリーミングしません」。成功すると、管理者の /agentic-coding/installs ページにインストールが表示されます。
メモ: 一部のアプリ内ヒントテキストにはまだ "Open Window → Enroll in bromure.io…" と表示されていますが、この項目は実際にはアプリケーション(アプリ名)メニューにあります。これが正式な場所です。別の Bromure アプリ用に発行されたコードは Code was issued for app '…', expected 'agentic-coding'. で拒否され、2回目の登録は Bromure Agentic Coding is already enrolled. で失敗します。
CLI から
GUI のフローには正確に対応する CLI があり、bromure-cli --help の Enterprise features の下にグループ化され、同じオンディスクストアを共有しています。スクリプトによるプロビジョニングや、既存の SSH セッション経由での登録に便利です。
| コマンド | 動作 |
|---|---|
bromure-cli enroll --code <code> [--server-url <url>] [--device-name <name>] | この Mac を登録します。成功時にはメール、ワークスペース、インストール ID、サーバー、デバイスを表示します。失敗時には非ゼロで終了します。 |
bromure-cli enrollment-status | 現在の状態を表示します。登録解除されている場合は not enrolled を表示し 0 で終了するため、自動化が安全にプローブできます。 |
bromure-cli unenroll [--force] | サインアウトします(取り消し、オフボーディング、登録解除 を参照)。 |
デフォルトは GUI と一致します。サーバー URL は https://bromure.io/api(BROMURE_MANAGED_URL または managed.serverURL UserDefaults キーで上書き可能)、デバイス名は Mac のローカライズされたホスト名です。
mTLS インストールアイデンティティ
テレメトリのアップロードはトークンを伴いません。クライアント証明書で認証します。登録時(および更新のたび)に、アプリは新しい RSA-2048 鍵を生成し、コモンネーム bromure-install-<installId> を持つ証明書署名要求を構築し、マネージドサーバーを通じてワークスペースの 組織 CA に署名させます。リーフ証明書と CA 証明書は検査可能な PEM ファイルとして保存され、秘密鍵は macOS キーチェーンに保存されます。
リクエスト時に、証明書と鍵はメモリ内の PKCS#12 にパッケージ化され、キーチェーンに触れることなくインポートされるため、アイデンティティ自体に対してキーチェーンアクセスのエントリやロック解除プロンプトが現れることは決してありません。分析エンドポイント自身のサーバー証明書は、通常のシステムルートストアに対して検証されます。
メモ: 登録中のリーフ証明書要求はベストエフォートです。組織 CA がまだ設定されていない場合でも登録は成功し、証明書は最初のハートビートで取得されます。
登録ステータスパネル
登録すると、同じメニュー項目は bromure.io Enrollment… に名前を変え、入力フォームの代わりにステータスパネル(タイトル bromure.io enrollment)を開きます。ここには Workspace、User、Device、Server、Enrolled(日付)、Certificate の各行が表示され、いずれもテキスト選択可能です。Certificate 行には Valid until <date> と表示されるか、期限が切れた場合は Expired — renewing automatically と表示されます。
下部には2つのボタンがあります。Renew certificate は新しいリーフ証明書を強制的に取得し、Sign out は登録を解除します(破壊的です。下記を参照)。ヘルスの問題はオレンジ色の警告バナーとして表示されます。
| バナー | 意味 | 対処 |
|---|---|---|
| Enrollment revoked | "Your administrator revoked this install. Sign out and enroll again with a new code to resume managed mode." | サインアウトして新しいコードで登録します。 |
| Enrollment no longer accepted | "The server rejected this install's credentials — they may have expired or been reset." | サインアウトして新しいコードで登録します。 |
Renew certificate が成功すると古い認証情報拒否状態はクリアされますが、revoked 状態がクリアされることは決してありません。それをクリアできるのは再登録だけです。
ハートビートと証明書の更新
アプリが登録された状態で実行されている間、バックグラウンドタスクが10分ごとに(および起動時と登録時に即座に1回)ワークスペースサーバーにハートビートを送信し、管理者の最終確認タイムスタンプを最新に保ちます。サーバーの応答はヘルスに関して信頼できるものです。取り消しはバナーを反転させ、正常な応答は以前の不良状態をクリアします。ハートビートのベアラートークンに対する 401/403 のみがヘルスを「トークン拒否」に変えます。一時的なエラー(オフライン、5xx)はそれを変えることは決してありません。
各ハートビートのティックでは mTLS リーフ証明書もチェックされ、証明書が欠落しているか有効期限まで 72 時間 以内になったときにはいつでも更新されます。更新はリーフではなくベアラートークンで認証されるため、すでに期限切れの証明書でも次回起動時に回復します。
警告: 証明書の有効期限を過ぎて閉じたままにされた Mac は、次回起動時にリーフが更新されるまで、マネージドアップロードが黙って失敗します。通常の使用では意識されませんが、マシンが長期間シャットダウンされたままになる場合は知っておく価値があります。
アップロードされるもの — されないもの
登録済みで非プライベートのセッションは、構造化された クラウドイベント をストリーミングします。1レコードにつき、セッション ID、ワークスペース ID、タイムスタンプ、イベントタイプ、そして小さな JSON ペイロードが含まれます。ここでのセッションは VM のライフサイクルではなくアクティビティウィンドウです。ワークスペースごと・アクティビティウィンドウごとに1つのセッション ID があり、20 分間の非アクティブ状態の後にロールオーバーされます。
| イベント | ペイロードのハイライト |
|---|---|
session.start / session.end | アクティビティウィンドウの開始と終了。session.end には理由(例: idle_timeout)が含まれ、アイドル境界にバックデートされます。 |
llm.request | プロバイダー、ホスト、パス、ステータスコード、レイテンシ、モデル、そして入力/出力/キャッシュのトークン数。リアルタイム WebSocket セッションではトランスポートとレスポンス ID が追加されます。 |
tool.use | ツール名と入力の要約(240 文字に切り詰め)。 |
file.read / file.write | ファイルパスと、それに触れたツール。 |
command.run | コマンドテキスト(500 文字に切り詰め)とツール。 |
credential.token_swap | ホストとパス、および偽のトークンと本物のトークンの短いプレビュー。トークンそのものは決して含まれません。 |
credential.ssh_sign | キーラベル、SHA-256 フィンガープリント、キーの種類(マネージド/インポート)。 |
credential.aws_sign | メソッド、ホスト、パス、サービス、リージョン、そしてマスクされたアクセスキー。 |
supply_chain.fetch | エコシステム、パッケージ、バージョン、リクエストの種類、結果、理由。 |
vm.disk_reset | 理由と、関与したベースイメージのバージョン。 |
prompt_injection.detection | 検出器、メソッド、アクション、ホスト、ソース、スコア、シグナル、ツール使用 ID、そしてフラグが立てられたスニペット全体(最大 20,000 文字)。 |
ストリーミングの状態はすべてのセッションウィンドウで確認でき、管理者が見るフリートレポートにもミラーリングされます。
Mac から決して出ていかないもの
ここは正確に述べるべき部分です。ストリームはメタデータであり、作業内容はローカルにとどまります。Bromure は 決して 以下をアップロードしません。
- 生のユーザープロンプト または モデル応答本文。
- シークレット値。 認証情報イベントはマスクされたプレビューまたはフィンガープリントのみを含みます。実際のキーバイトが Mac から出ていくことは決してありません。
- プライベートモードのワークスペースからのあらゆるもの(下記参照)、そして 登録解除されているときは一切何も。
バッファされたイベントはメモリ内にのみ保持されます。強制終了すると、まだフラッシュされていないものは破棄され、ディスクベースの再試行キューはありません。これは設計上受け入れられています。テレメトリはベストエフォートであり、作業を犠牲にすることは決してありません。
警告: メタデータのみのルールには意図的な例外が1つあります。
prompt_injection.detectionは フラグが立てられたスニペット全体(最大 20,000 文字)をアップロードするため、管理者はエージェントがまさに読み込もうとしていたものを正確に確認できます。これはメタデータではなくコンテンツです。トレードオフとして、プロンプトインジェクションの試みこそが、セキュリティチームが逐語的に検査する必要のあるものです。それ以外はすべてプレビュー、パス、カウント、マスクのままです。何が検出をトリガーするかについては プロンプトインジェクション保護 を参照してください。
バッチ処理と配信
イベントはメモリ内でバッチ化され、分析取り込みエンドポイントに送信され、mTLS リーフ証明書のみで認証されます。テレメトリデータにベアラートークンが伴うことはありません。バッファは5秒ごとにフラッシュし、保留中イベントが 200 件になると自動フラッシュし、1リクエストあたり最大 500 件のイベントを送信します。長時間の障害中は、バッファは無制限に増大するのではなく最新のイベントに切り詰められ(最も古いものが破棄されます)、フラッシュに失敗すると次のティックで同じバッチを再試行します。
プライベートモード
ストリーミングはワークスペースごとのオプトアウト方式です。ワークスペースのエディタにある Private mode トグル(目に斜線のアイコン)は、そのワークスペースのアクティビティを完全にローカルに保ちます。メタデータはストリーミングされず、そのワークスペースではタイトルバーのインジケーターが消え、管理者のセッションリストにはそこから何も表示されません。ローカルのトレースインスペクタは影響を受けません。独自の トレースレベル に従って記録を続けます。トグルはすべてのワークスペースでオフ(ストリーミング有効)であり、登録済みの Mac にのみ表示されます。そうでなければ何も行わないためです。
プライベートモードは、ワークスペースエディタの トレース 設定とともにあります。登録解除された Mac ではスイッチが単に存在しないため、以下のペインにはトレースピッカーのみが表示されます。
イベントは送出時にゲートされます。プライベートモードのトラフィックはアップロードバッファに入ることすらありません。
ヒント: プライベートモードは、あるワークスペースで個人の API キーを使用していて、そのアクティビティを組織の管理者に見せたくない場合に適したスイッチです。ローカルの監査証跡については何も変えません。
ストリーミングインジケーター
Mac が登録されていて、ワークスペースがプライベートモードでない場合は常に、そのセッションウィンドウのツールバーに脈打つ赤い録画スタイルのドットが表示されます(統合ウィンドウのサイドバー行にもドットとして表示されます)。そのツールチップには "Session metadata is being sent to bromure.io. Toggle the workspace's Private Mode to stop streaming." と表示され、アクセシビリティラベルは Streaming to bromure.io です。このドットは純粋に情報提供のためのもので、登録解除されているときやプライベートモードのときは非表示になります。
エグレス IP の登録
登録済みのインストールはまた、60 秒ごとに(および起動時と登録時に1回)、分析サービスの /register-ip エンドポイントに小さな mTLS 認証の ping を送信し、ワークスペースのレコードが Mac の現在のパブリック IP を反映するようにします。登録解除されているときは黙ってスキップされます。エンドポイントのデフォルトは https://analytics.bromure.io/register-ip で、BROMURE_AC_REGISTER_IP_URL または managed.acRegisterIPURL UserDefaults キーで上書き可能です。
サプライチェーンインベントリとトークン使用量のロールアップ
ストリーミングされるイベントタイプのうち2つは、チーム全体にわたってエンタープライズ層のレポートを有用にするものです。
- サプライチェーンインベントリ。 すべてのメタデータおよびアーティファクトの取得は、エコシステム、パッケージ、バージョン、リクエストの種類、結果(
allowed、rewritten、blocked、stripped)、理由を含むsupply_chain.fetchイベントを送出します。登録だけで、管理者は各エージェントが取り込んだすべてのパッケージの組織全体のインベントリを得られます。観察は強制と切り離されているため、すべてのサプライチェーン強制レイヤーをオフにしたワークスペースでも同様です。この強制側は サプライチェーン保護 に記載されています。 - トークン使用量のロールアップ。 すべての
llm.requestイベントには、モデル、入力および出力のトークン数、キャッシュ作成およびキャッシュ読み取りのカウントが含まれます。フリート全体で集計すると、プロンプトや応答のコンテンツを一切アップロードすることなく、ユーザーごと、ワークスペースごと、モデルごとの支出レポートになります。ローカルの対応物(自分の Mac で読める、リクエストごとのトークン集計)は トレース にあります。
フリートビュー
bromure.io 側では、登録された各 Mac は、ワークスペースの /agentic-coding/installs ページに行として表示され、インストール ID で識別され、設定したデバイス名、ユーザー、そして10分ごとのハートビートによって最新に保たれる最終確認タイムスタンプを示します。そこから管理者は、フリート全体のストリーミングされたセッションメタデータ、サプライチェーンインベントリ、トークン使用量のロールアップ、プロンプトインジェクション検出を確認します。
これは、複数のリモートホストを SSH 経由で一度にミラーリングするというリッチクライアントの「フリート」の概念とは異なります。そちらは リモートアクセス で扱います。両者はトラストルートを決して共有しません。
リモートの同意処理
ワークスペースセッションが CLI または SSH 経由でインタラクティブにアタッチされている場合(前面に GUI ウィンドウがない場合)、アプリはダイアログをポップアップできません。代わりに、4つの中間者同意ブローカーは、その質問をアタッチされたユーザーのターミナル上に番号付きメニューとしてレンダリングします。
| プロンプト | 選択肢 |
|---|---|
認証情報の使用 — Allow "<workspace>" to use <credential>? | Allow for 1 hour / Allow for 5 minutes / Allow for the rest of the session / Don't allow |
サプライチェーンのバイパス — Pass through <package> from workspace …? | Allow for 15 minutes / Allow once / Allow for the rest of the session / Don't allow |
ガードレールの書き込み — Allow write on … from workspace …? | (上記と同じ4つ) |
プロンプトインジェクション — Possible <detector> in …(フラグが立てられたテキストを最大 1,500 文字表示) | Block this request / Allow this request |
決定的な特性は、プロンプトがどこでレンダリングされるかです。ターミナルポンプの ホスト 側です。ゲスト VM は接続のもう一方の側しか見えないため、侵害されたゲストはプロンプトを読むことも、回答を注入することもできません。複数のクライアントが同じワークスペースにアタッチしている場合、最新のインタラクティブアタッチがプロンプトを受け取ります(「最新のアタッチが勝つ」)。
警告: これらのプロンプトはフェイルセーフです。ライブアタッチがない、タイムアウト(デフォルト 120 秒)、却下、プロンプトの途中でのデタッチは、すべて 拒否 に解決されます。プロンプトインジェクションの場合は ブロック に解決されます。レジストリ認証失敗のアラートは、インタラクティブにアタッチされたセッションではログ行に抑制されます。それを表示する GUI がないためです。これらと同じ決定の GUI パスは、認証情報、サプライチェーン保護、プロンプトインジェクション保護 で扱います。
取り消し、オフボーディング、登録解除
インストールがフリートから離れる方法は2つあり、それぞれ異なる動作をします。
登録解除(ローカル)。 登録ステータスパネルで Sign out をクリックするか、bromure-cli unenroll を実行します。CLI は --force を渡さない限り Sign out of <org> (<email>)? [y/N] とプロンプトを出し、削除するものがないときは not enrolled — nothing to do(終了 0)を表示します。サインアウトすると、すべてのローカル登録マテリアル(install.json、leaf.crt、ca.crt、leaf.serial、ヘルスファイル)を削除し、キーチェーンからベアラートークンとすべてのリーフ秘密鍵を削除し、キャッシュされた mTLS アイデンティティをパージし、バッファされたテレメトリを破棄し、ハートビートと IP 登録タスクを停止します。アプリは Not enrolled 状態に戻り、ステータスウィンドウは登録フォームに切り替わるため、すぐに別のコードで再登録できます。
取り消し(サーバー側)。 管理者は bromure.io 上でインストールを取り消します。Mac 側では、次のハートビートで Enrollment revoked バナーが表示され、マネージドアップロードが停止します。
警告: サインアウトは純粋にローカルです。サーバー呼び出しは行われません。デバイスを廃止する管理者は インストールをサーバー側で取り消す べきです。そうしないと、(すでに死んだ)インストール行は、ハートビートが停止するまでフリートページに残り続けます。Mac を完全にオフボードするには、ワークスペースでそれを取り消し、かつ デバイスでサインアウトします。
リファレンス
登録状態は ~/Library/Application Support/BromureAC/managed/ の下にあります。install.json(インストール ID、ワークスペーススラッグ、ユーザー、サーバー URL、デバイス名、登録日時)、leaf.crt と ca.crt(PEM)、leaf.serial(現在のリーフのキーを保持するキーチェーンエントリへのポインタ)、そして health(ok / tokenRejected / revoked)です。macOS キーチェーンでは、サービス io.bromure.agentic-coding.managed-install が install-token ベアラーと、発行された証明書シリアルごとに1つの leaf-cert-key-<serialHex> エントリを保持します(このデバイスのみ、ロック解除時)。
クライアントは、3つのマネージドサーバールートと1つの取り込みエンドポイントに接続します。
POST {server}/v1/enroll (code redemption)
POST {server}/v1/installs/{installId}/heartbeat (Bearer)
POST {server}/v1/installs/{installId}/cert (Bearer + CSR PEM)
POST {ingest URL} {"events":[…]} (mTLS, no bearer)
| 間隔 / 制限 | 値 |
|---|---|
| ハートビート | 10 分ごと |
| エグレス IP 登録 | 60 秒ごと |
| リーフ更新のしきい値 | 有効期限の 72 時間前 |
| イベントフラッシュ | 5 秒ごと(または保留 200 件時) |
| バッチあたりの最大イベント数 | 500 |
| セッションのアイドルロールオーバー | 20 分 |
| リモート同意のタイムアウト | 120 秒 |
| プロンプトインジェクションスニペットの上限 | 20,000 文字 |
サーバーとエンドポイントの上書き(GUI なし)は、BROMURE_MANAGED_URL(または managed.serverURL、デフォルト https://bromure.io/api)、BROMURE_AC_INGEST_URL(または managed.acIngestURL、デフォルト https://analytics.bromure.io/ac-ingest)、BROMURE_AC_REGISTER_IP_URL(または managed.acRegisterIPURL)です。完全なコマンドリファレンスは 自動化と CLI にあります。