コンテンツにスキップ

ADR-0052: 実行環境が追加するファイルを、訪問者の作業ディレクトリの外に置き、preload を NODE_OPTIONS で渡す

Status

承認

Context

実行環境が追加するファイル(preload、DB のプロセスのスクリプトと依存、待ち受けたポートの URL を書くファイル)の置き場と、preload を訪問者のプロセスに追加する方法を決める必要がある。

Decision

1. ファイルの置き場

実行環境が追加するファイルは、訪問者の作業ディレクトリの外(/tmp の下の、実行環境のディレクトリ)に置く。

  • 対象は、preload のファイル、DB のプロセスのスクリプトと依存、待ち受けたポートの URL を書くファイルである。
  • 訪問者のファイルのツリーと、作業ディレクトリには出ない。保存の対象にも入らない。
  • 待ち受けたポートの URL を書くファイルのパスは、環境変数で渡す。Node のコードは、環境変数からパスを読む。

2. preload の追加の仕方

実行環境は、起動のコマンドのプロセスと、シェルに、環境変数 NODE_OPTIONS を渡す。
実行環境が自分で起動するプロセス(DB のプロセス、DB の依存の npm install)には、preload を追加しない。

  • NODE_OPTIONS には、preload ごとに --require <絶対パス> を並べる。
  • 起動のコマンドを、書き換えない。
  • preload は、役割ごとにファイルを分ける。使わない役割の preload は、追加しない。
  • 訪問者が NODE_OPTIONS を上書きして、preload が読み込まれなくなっても、対応しない。

NODE_OPTIONS で渡す理由は、訪問者がシェルで打ったコマンドと、npm run が起動する node にも、preload が追加されるためである。

承認の条件

  • 待ち受けたポートの URL を書くファイルを、/tmp の下に置いて、訪問者のコードから読めることを確認している。
  • ファイルを /tmp の下に置く手順(WebContainers の API で直接書くか、作業ディレクトリに書いてから移すか)を決めている。

Verification

WebContainers 1.6.4 の中の Node 24.22.2 で測った。
マシンは Apple M2、ブラウザは Playwright 1.65.0 の Chromium、WebKit、Firefox(headless)、配信は localhost である。実機のブラウザは未確認である。

preload は、Unix ドメインソケットに接続している間はプロセスを終了させないもの(ADR-0053)と、HTTP の流れを記録するもの(ADR-0054)の 2 つを使った。
短いスクリプトは、pg の Pool か Client で、クエリを 3 つ実行して end() を呼ぶ。

起動の仕方 NODE_OPTIONS Chromium WebKit Firefox
node app.js 無し 途中で終了 Client が途中で終了 最後まで実行
node app.js --require ./<preload>(相対パス) 最後まで実行 最後まで実行 最後まで実行
node app.js --require <絶対パス> 最後まで実行 最後まで実行 最後まで実行
node app.js 2 つの preload 最後まで実行 最後まで実行 最後まで実行
npm run seed(scripts が node app.js を呼ぶ) 2 つの preload 最後まで実行 最後まで実行 最後まで実行
シェル(jsh)を起動し、入力に node app.js を書く 無し 途中で終了 最後まで実行 最後まで実行
シェル(jsh)を起動し、入力に node app.js を書く 2 つの preload 最後まで実行 最後まで実行 最後まで実行
  • 2 つの preload は、--require の順序のどちらでも、同じ結果だった。
  • HTTP のサーバー(リクエストの中で pg のクエリを実行する)に、2 つの preload を追加し、別のプロセスから fetch した。クエリの結果が返り、HTTP の記録の行が 1 件出た。3 つのブラウザで同じだった。
  • preload のファイルを /tmp の下に置き、NODE_OPTIONS=--require /tmp/<ディレクトリ>/<preload> で渡すと、preload が動いた。作業ディレクトリの ls -a には、出なかった。ls -a /tmp には、出た。
  • 試作では、ファイルを作業ディレクトリに mount してから、node -e で /tmp へ移した。WebContainers の API で、作業ディレクトリの外に直接書けるかは、未確認である。
  • 待ち受けたポートの URL を書くファイルを、/tmp の下に置いて、訪問者のコードから読む形は、試していない。

Considered Options

preload のファイルの分け方の選択肢は次のとおり。

選択肢 強み 弱み
採用: 役割ごとにファイルを分け、--require を並べる ADR-0053 と ADR-0054 の preload が、別のファイルになる。使わない役割の preload を追加しない NODE_OPTIONS の値を、プロジェクトの設定から組み立てる
1 つのファイルにまとめ、環境変数で機能を切り替える --require が 1 つで済む 2 つの ADR の preload が、1 つのファイルに入る

preload の追加の仕方と、ファイルの置き場の選択肢は次のとおり。

選択肢 強み 弱み
採用: NODE_OPTIONS で渡し、ファイルを /tmp の下に置く 起動のコマンド、npm run、シェルで打ったコマンドのプロセスに渡る。ファイルのツリーと作業ディレクトリに出ない。保存の対象に入らない 訪問者が NODE_OPTIONS を上書きすると、preload が読み込まれなくなる。ls /tmp には出る
NODE_OPTIONS で渡し、ファイルを作業ディレクトリの中に置く /tmp へ移す処理が要らない ls -a に出る。保存の対象から除く処理が要る。訪問者が消せる
起動のコマンドを、node -r <preload> ... に書き換える 環境変数に依らない シェルで打ったコマンドと、npm run の中の node には、preload が追加されない

待ち受けたポートの URL を書くファイルの置き場の選択肢は次のとおり。

選択肢 強み 弱み
採用: /tmp の下に置き、パスを環境変数で渡す 保存の対象に入らないので、再訪のときに、古い URL が戻らない Node のコードが、環境変数からパスを読む 1 行を持つ
作業ディレクトリの中に置き、保存の対象から除く 訪問者が、ファイルのツリーで中身を見られる 保存の対象から除く規則が増える。訪問者が書き換えられる

Consequences

Positive

  • 訪問者が、端末で node、npm run のどちらを使っても、preload が追加される。
  • 訪問者のファイルのツリーと、保存したファイルに、実行環境のファイルが入らない。

Negative

  • 訪問者が、端末で ls /tmp を実行すると、実行環境のファイルが見える。
  • 訪問者が NODE_OPTIONS を上書きすると、HTTP の記録が取れなくなる。
  • Node のコードは、待ち受けたポートの URL を、環境変数が指すファイルから読む。