0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

"AIに渡す前の初回フォームCSVをNode.jsで止める"

0
Posted at

美容サロンやウェルネス系の初回フォームでは、予約メニューよりも「備考」欄が危険になりがちです。肌が弱い服薬あり妊娠中 のような情報がCSVの自由記述に残ったままAIへ渡ると、プロンプトで「個人情報は扱わないで」と書いても入口で負けています。

この記事では、実データを使わず、ローカルの架空fixtureだけで「AIへ渡す前のCSVに危ない列名や値があれば終了コード1にする」最小パターンを書きます。Claude Codeのpermissionsとsandboxは公式ドキュメントで確認し、ここでは実装の形に絞ります。

前提のフォルダ分離

原本とAI用コピーを同じ場所に置かない前提にします。

  • intake-raw/: 原本フォーム、氏名、電話、メール、自由記述、写真、決済文脈
  • intake-ai-work/: 架空ID化または匿名化したCSV、分類表、下書き材料
  • intake-approved/: 人が確認したチェックリストと送信用文面

Claude Codeの公式ドキュメントでは、permissionsはRead、Edit、Bashなどのtool権限を制御し、sandboxはBashコマンドや子プロセスのファイル・ネットワーク境界を作るものとして説明されています。つまり、設定だけに頼らず、入力ファイル自体を先に減らします。

最小のpreflightコード

以下はコピペで動くNode.js例です。実CSVを読まず、通してよい架空データと止めたい架空データを配列で持たせています。

const files = [
  {
    path: "intake-ai-work/intake-redacted.csv",
    text: "intake_id,menu,consent,contraindication_category,staff_review\nB-001,trial_facial,true,sensitive_skin,true"
  },
  {
    path: "intake-ai-work/bad.csv",
    text: "name,email,medication_note\nAiko,aiko@example.com,blood pressure medicine"
  }
];

const blockedFields = [
  "name",
  "email",
  "phone",
  "address",
  "birthdate",
  "medication",
  "diagnosis",
  "pregnancy_week",
  "free_note"
];

const valuePatterns = [
  /[\w.+-]+@[\w.-]+\.[A-Za-z]{2,}/,
  /\b\d{2,4}-\d{2,4}-\d{3,4}\b/,
  /\b(?:medicine|diagnosis|pregnant|allergy)\b/i
];

const findings = [];

for (const file of files) {
  const lowerText = file.text.toLowerCase();
  for (const field of blockedFields) {
    if (lowerText.includes(field)) {
      findings.push({ path: file.path, type: "blocked field", field });
    }
  }
  for (const pattern of valuePatterns) {
    if (pattern.test(file.text)) {
      findings.push({ path: file.path, type: "blocked value", pattern: String(pattern) });
    }
  }
}

console.table(findings);
if (findings.length > 0) {
  process.exitCode = 1;
}

bad.csv 側に emailmedication_note が入っているため、終了コードは1になります。ここで大事なのは、検出値を長くログに出さないことです。メールアドレスや薬名をログへ再掲すると、検査コードが新しい漏えい経路になります。

終了コードの扱い

この検査では、終了コード1を「Claude Codeへ渡さない」という合図にします。0は「完全に安全」ではなく、「この小さな検査では止まらなかった」という意味です。0でも、スタッフが intake-ai-work/ のCSVを開き、自由記述がカテゴリ化されているか、staff_review が必要な行に立っているかを見ます。

CIに入れる場合も、失敗ログには値そのものを出しません。blocked field: email のように項目名だけ出せば、直す人には十分です。検査の目的は、危険な値を詳しく表示することではなく、AI入力前に作業を止めることです。

実ファイル版へ広げる時

実ファイルを読む版に変える時も、対象は intake-ai-work/ だけです。intake-raw/ は読まない設計にします。拡張子は最初から .csv.json.md.txt などに絞り、PDFや画像が来たら「未対応」として止めます。黙って通すより、対応外を人の確認へ戻すほうが事故を減らせます。

完全な業務フロー、権限境界、スタッフ確認、ROIの測り方は、美容・ウェルネス初回フォームのpreflight全体設計にまとめています。

よくある失敗

一つ目は、列名だけを見ることです。note の中に薬、妊娠、アレルギー、住所が入ると列名チェックだけでは通ります。上の例では簡単な正規表現も入れていますが、手書き画像や複数列を組み合わせた本人推定までは見ません。

二つ目は、検査を本物の予約CSVで試すことです。ターミナル履歴、スクリーンショット、CIログに値が残ります。許可サンプルも拒否サンプルも、架空IDと架空メールだけで作ります。

三つ目は、正規表現を増やしすぎることです。検出を細かくするほど誤検知も増えます。最初は「危ない列名」「メールや電話らしい値」「健康や薬らしい英単語」の3つに絞り、止まった件数と人の確認結果を見て足します。

運用に入れる境界

このコードだけで安全とは言いません。Claude Code側では intake-raw/ をdenyし、sandbox側でも原本フォルダを読めないようにします。さらに、AIに渡すCSVは許可列方式にして、自由記述は短いカテゴリやフラグへ変えます。

公式情報として、Claude Code permissions、settings/sandbox、個人情報保護委員会の個人情報ページを確認しました。個別の法務・医療・施術判断は、自社の責任者や専門家が行う前提です。

まとめ

AI入力前チェックは、完全な匿名化ツールではありません。それでも、明らかに渡してはいけない列や値を止めるだけで、初回フォームの事故は減らしやすくなります。原本、AI用コピー、人の承認、送信先を分け、止まった件数も記録するのが最初の一手です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?