Claude Code × Medical Application
【Claude Code】目視の確認を自動チェックに Part4:公開と運用 — 帳票を受け取らない設計

1. はじめに — 帳票は外に出せない
申請前の帳票は、会社の中でもっとも外に出しにくい資料の1つです。試験の結果そのものが載っていて、社外のサービスに上げてよいかは、社内の手順で厳しく決められているのがふつうです。
便利な確認ツールがあっても、「PDF をこのサイトに送ってください」という形では、製薬の現場では使ってもらえません。そこで TLF Visual QC は、最初から次の形に決めていました。
- 帳票を受け取らない:計算はすべて、使う人のブラウザの中で行う
- サーバーは画面を配るだけ:受け取る仕組みそのものを持たない
- 外への通信を止める:画面の部品も含めて、サイトの外に何も取りに行かない
この回では、この形をどう作り、どう確かめたかを見ていきます。
- 構成 — サーバーを持たない
- 外への通信を止める仕組みと、確かめ方
- 本番の環境でだけ起きた不具合
- 通信を切っても動くようにする
- 配信元が付け足すもの — 通信エラーの報告と、解析のスクリプト
- 検証済みでないツールとしての位置づけ
- 例の帳票を同梱しない理由
- 0件PDF を読み込んで計算する間の、サイトの外への通信
- 約200件画面を開いたときに読み込むファイル(すべて同じサイトの中)
- 0サーバー側で動くプログラム(画面のファイルを配るだけ)
- 3つ本番の環境でだけ起きたこと(書体のずれ、通信エラーの報告、解析のスクリプト)
2. 構成 — サーバーを持たない
TLF Visual QC は、HTML・JavaScript・PDF.js のデータファイルだけでできた 静的なサイト です。Cloudflare Pages に置いていて、サーバー側で動くプログラムはありません。
| DPC のダッシュボード | TLF Visual QC | |
|---|---|---|
| 置き場所 | Cloudflare Pages | Cloudflare Pages |
| サーバー側の処理 | あり(AI への問い合わせを中継し、返答を検査する) | なし |
| 外部のサービス | 生成 AI(Claude) | なし |
| 利用者のデータ | 質問の文がサーバーと AI を通る | PDF はブラウザから出ない |
| 費用 | AI の利用料(1問あたり約0.1円) | 配信だけ |
連載「社内の BI を AI ダッシュボードに」のダッシュボードは、質問を AI に送るためにサーバー側の処理を持っていました。このツールには AI もサーバー側の処理もないので、受け取ったデータを守る仕組みを考える必要が、そもそもありません。受け取らない作りがいちばん確実な守りです。
PDF を読み込むと、ブラウザの中で次の順に処理されます。
- PDF.js がページを画像に描く(Part1 の手順)
- 別の作業用のスレッド(Worker)で、灰色化・縮小・白の割合の計算をする
- 結果の表とページの画像を画面に出す
ページの画像も結果も、ブラウザのメモリにあるだけです。画面を閉じれば消えます。
3. 外への通信を止める仕組みと、確かめ方
3-1. CSP — ブラウザに「外に出るな」と伝える
「外に送る処理を書いていない」だけでは、まだ足りません。将来だれかが部品を足したときに、その部品が外に通信するかもしれないからです。
そこで、サイトの応答に CSP(コンテンツ セキュリティ ポリシー) を付けています。ブラウザに「このページは、同じサイトのファイルしか読み込まない、同じサイトにしか通信しない」と伝える設定で、ブラウザがこれを守ります。外のサーバーへの通信は、ページのプログラムが試みてもブラウザが止めます。

解析のタグや広告、外部のフォント、CDN からの部品も使っていません。必要な部品は、すべてサイトに同梱しています。
3-2. 確かめ方 — 通信の記録を見る
実際に外への通信がないかは、ブラウザの開発者ツールで通信の記録を見れば確かめられます。
ブラウザの通信の記録を、3つの段に分けて取りました。
| 段 | 通信 | 行き先 |
|---|---|---|
| 画面を開く | 約200件 | すべて同じサイトの中(画面のファイル、PDF.js の書体や文字の対応表、ダミーの帳票) |
| ダミーの帳票を読み込み、30ページを計算する | 外へは0件 | ブラウザの中だけ(30ページを約0.7秒、CHECK 8ページ) |
| CHECK のページの画像を開く | 外へは0件 | ブラウザの中だけ |
画面を開いたときの約200件は、書体などの PDF.js のデータを先に読んでおくためです(5章)。PDF を読み込んで計算する間に、外への通信は増えません。
4. 本番の環境でだけ起きた不具合
手元の開発用の環境では、テストがすべて通っていました。ところが、公開用にビルドしたもので同じダミーの帳票を読み込むと、改ページの値がずれました。
原因は書体でした。PDF.js は、PDF に埋め込まれていない書体を描くために、書体のデータファイルを読みに行きます。ビルドしたものでは、そのファイルの置き場所を PDF.js が取り違え、代わりの書体で描いていた のです。代わりの書体は文字の幅や形が違うので、白い画素の数が変わり、白の割合がずれます。画面には何のエラーも出ず、結果の表は普通に出ていました。
直したあと、本番と同じ形でビルドしたものを、実際のブラウザで動かして確かめる テスト(check:build)を足しました。開発用の環境だけで確かめていると、ビルドのときにだけ起きる違いを見逃すからです。いまは、公開する前に必ずこのテストを通しています。
5. 通信を切っても動くようにする
5-1. 最初の版では動かなかった
PDF をブラウザの中だけで扱うなら、画面を開いたあとに通信を切っても動くはずです。これは「外に送っていない」ことのいちばん分かりやすい証拠にもなります。
ところが、最初に公開した版では、通信を切ると「この PDF は開けませんでした」になりました。PDF.js の Worker や書体のデータを、PDF を開くたびにサイトから読み直していて、それらが「使うたびにサーバーに確かめる」設定で配られていたためです。
5-2. 直し方
- 画面を開いた時点で、必要なものを先に読んでおく:PDF.js の Worker と計算用の Worker を立ち上げ、書体などのデータ(約2.4MB)とダミーの帳票をメモリに読み込んでおく。PDF.js には、サイトからではなくメモリから渡す
- 名前が中身で決まるファイルは、長く手元に置いてよいと伝える:ビルドで名前に印が付くファイルと、版番号の付いたフォルダに置いた PDF.js のデータは、中身が変わらないので、ブラウザに長く置いてよい(immutable)と設定した
画面を開いて読み込みが終わってから通信を切れば、ダミーの帳票も自分の PDF も、通信があるときと同じ結果で計算できます。

この確かめも、本番と同じ形のテスト(check:build)に入れています。
6. 配信元が付け足すもの — 通信エラーの報告と、解析のスクリプト
本番のドメイン(visual-qc.herzleben.co.jp)に切り替えたあと、公開版の応答とブラウザの動きを確かめていて、配信元の Cloudflare が自動で付け足しているもの が2つ見つかりました。どちらもツールが外に送るものではありませんが、「外への通信はない」と言い切るために止めています。
6-1. 通信エラーの報告(Network Error Logging)
Cloudflare は、応答に 通信エラーの報告(Network Error Logging)を頼むヘッダー(nel と report-to)を付けていました。
- ブラウザがこのサイトとの通信に失敗したとき(つながらない、エラーが返る、など)に、失敗した URL や時刻などを Cloudflare に知らせる仕組み
- Chrome や Edge が対応している
- PDF の中身やファイル名は含まれない(PDF は通信に乗らないため)
- CSP の対象外で、ページの側からは止められない
管理画面でこの設定を切りましたが、10分たってもヘッダーは付いたまま でした。そこで、応答からこの2つのヘッダーを消すルールを herzleben.co.jp のドメインに足し、ヘッダーが消えたことを確かめています。以前にサイトを開いたブラウザには、最長7日間、前の指示が残ることがあります。
6-2. 解析のスクリプトの差し込み(Web Analytics)
もう1つは、本番の形のテスト(check:build)を公開版に向けて回したときに見つかりました。外への通信と、CSP の違反の警告が出ていたのです。
原因は、herzleben.co.jp のドメインで有効にしていた Cloudflare のアクセス解析(Web Analytics)でした。会社のサイトの訪問者を数えるための設定ですが、同じドメインの下にあるこのツールのページにも、解析用のスクリプトを自動で差し込んでいました。CSP が止めるので実際には送られませんが、ブラウザは読み込もうとして、警告を出していました。
- curl のような道具で応答を取っても差し込みは見えず、ブラウザで開いたときだけ 現れる
- 直し方:ツールの HTML の応答に
no-transform(配信元に中身を書き換えないよう伝える指定)を付けた。会社のサイトの解析はそのまま
7. 検証済みでないツールとしての位置づけ
7-1. 断り書き
ツールの入口と About には、次の断り書きを置いています。
本ツールは検証済みのツールではありません。結果は目視確認の補助として使い、最終的な判断は各社の手順に従って行ってください。PDF はお使いのブラウザの中だけで処理され、外部には送られません。
初めて開いたときは、入口のページで目的・使い方・データの扱いとあわせてこの断り書きを読み、同意してから使い始める形にしています(同意は30日有効)。

7-2. なぜ「検証済み」と言わないか
製薬の業務で使うシステムは、多くの会社で、使う目的に合っていることを手順に沿って確かめ、記録を残してから使います(コンピュータ化システムバリデーション、最近はリスクに応じて確かめ方を絞る CSA の考え方も広がっています。解説記事)。
このツールは、Part2 で紹介したとおり、部品・全体・現実の3段で確かめています。ただ、それは 作る側の確かめ で、各社の業務の手順に沿った確かめではありません。使う会社ごとに、どの帳票に、どの段階で、どう使うかが違うからです。
そのため、このツールは目視の確認を置き換えるものではなく、目で見るページと色を絞り込むための補助 としています。社内の手順に組み込むなら、各社の手順に沿って確かめる必要があります。
7-3. 手法の限界も書いておく
About には、手法の限界も書いています。
- もともと短い表のページにも CHECK が付く
- 脚注やフッターが測る範囲の下半分にあると、白の割合が下がり、見逃すことがある
- 色覚のシミュレーションは二色覚を想定した目安で、実際の見え方を保証しない
限界を書いておくのは、印が付かなかったページを「問題なし」と読まれないようにするためです。
8. 例の帳票を同梱しない理由
ツールには、最初からダミーの帳票と例の配色が入っていて、すぐに試せます。一方、Part2 で使った R Consortium の申請パイロットの帳票は、同梱せず、リンクで案内 しています。
- 申請パイロットの資料は、今後の申請の手本として誰でも見られるように公開されている
- ただし、帳票の PDF にはライセンスの表示がなく、HerzLeben が複製して配ってよいとは書かれていない
- 利用者が自分でダウンロードしてツールに読み込むなら、PDF はその人のブラウザの中で処理されるだけで、こちらが配ることにはならない
公開されているものでも、配ってよいとは限りません。ダミーは自前で作り、公開の帳票はリンクで案内する、と分けています。
9. まとめ
- 申請前の帳票は外に出せない。だから最初から、帳票を受け取らず、計算をすべてブラウザの中で行う形にした
- サーバーは画面を配るだけで、CSP で外への通信を止めている。通信の記録で、誰でも確かめられる
- 公開用にビルドしたものでだけ、書体を取り違えて白の割合がずれた。本番と同じ形で確かめるテストを足した
- 必要なものを画面を開いた時点で先に読むようにし、通信を切っても同じ結果で計算できるようにした
- 配信元が付け足す通信エラーの報告のヘッダーと、解析のスクリプトの差し込みも止めた。どちらも本番のドメインを実際のブラウザで確かめて見つかった
- 検証済みでないツールとして、目視の補助に位置づけ、手法の限界とあわせて明記している
データを守るいちばん確実な方法は、データを受け取らないことです。そのうえで、受け取っていないことを、誰でも確かめられる形にしておくことです。
次のステップ
連載はここまでです。全体像と使いどころは Part0 にまとめています。社内の帳票の決まりに合わせたチェックや、社外に出せないデータを扱うツールのご相談は、お問い合わせからお寄せください。
出典
- Yi Guo. Detecting Abnormal Page Breaks Using Grayscale Pixel-Density Analysis in R Shiny. PharmaSUG 2026, Paper AP-233. https://pharmasug.org/proceedings/2026/AP/PharmaSUG-2026-AP-233.pdf
- R Consortium R Submission Working Group. submissions-pilot1-to-fda. https://github.com/RConsortium/submissions-pilot1-to-fda
- Cloudflare. Understanding Network Error Logging. https://developers.cloudflare.com/support/network/understanding-network-error-logging/
- Cloudflare. Web Analytics FAQ. https://developers.cloudflare.com/web-analytics/faq/
- 本ページの画面写真は、架空のデータで作成したダミーの帳票を読み込んだものです
