甲斐犬のキクと元宇品の山
墓参り
内部監査支援システムの構築
LLM(AI)に対するセキュリティ対策
AIに監査の内容を検討依頼するにはセキュリティの観点から、固有名詞等は排除しなくてはならない
固有名詞辞書を作成して、入力後チェックが行われるようにするが、まだ色々と誤検知が多いので修正
- 工種辞書(一般的な工事種別のストップワード化)、建設業の一般工種は固有名ではない。stopwordsに追加:PC杭打工事, 杭打工事, 杭工事, 土工事, 鉄筋工事, 型枠工事, 躯体工事, 仮設工事・・・・
- 関係節ガード:名前部分に連体修飾の接続語が含まれる場合は名称でなく説明文なので検出しない:
に関する|に係る|を伴う|における|についての|に対する(例:「騒音に関する工事」「振動を伴う工事」は非検出) - 接頭辞の反復剥がし:検出語の先頭から以下を繰り返し除去し、残りが工種辞書・stopwordsに一致すれば非検出とする:
\d+件の|\d+つの|この|その|各|両|全|当該|同|工区の|作業所の|現場の|支店の(例:「各工区の土工事」→「各」除去→「工区の」除去→「土工事」=工種辞書→非検出)
パターン照合には原理的な精度限界があるため、確度に応じて扱いを分ける:
- ブロック級(修正しないと先に進めない。従来通り):
- 会社形態(株式会社/㈱等)、敬称付き人名(〜さん/氏/様)、識別子(認証番号等)、動的辞書・user_stopwords外のラベル由来一致
- 注意級(黄色ハイライト+「固有名の可能性。問題なければそのまま進めます」。
クリック不要で続行可能):
工事名catch-all、作業所/建物、地名系(市/川/駅等)、役職付き人名、部署系
ハイライト色を分け(赤=ブロック級、黄=注意級)、注意級のみの場合は次へ進むボタンを有効のままとする。metrics.jsonlに「注意級を残したまま進んだ件数」を記録(実運用での注意級の妥当性評価用)。
v1.1の「一般名称として許可」ボタンは両級で引き続き有効。
待ち時間UX(API呼び出し中の表示)
全API呼び出し(/api/clarify, /api/factdraft, /api/candidates, /api/generate)に:
- ボタンを即時無効化+スピナー表示(二重送信防止)
- 段階メッセージを表示: 例
candidates: 「類似事例を検索しています…」→(API送信後)「条項を判定しています…」
factdraft: 「事実文を作成しています…」
generate: 「指摘文案を作成しています…」 - 経過秒数を小さく表示(「(12秒)」)
- 可能なら /api/generate と api/factdraft はストリーミング応答(SSE)で文章を逐次表示する。実装が重い場合はスピナー+段階メッセージまでで可(その場合はREADMEに今後の課題として記載)
- タイムアウト(120秒)時は再試行ボタンを表示
ひろしまみなとマルシェに 内部監査支援システム開発
朝は元宇品に散歩に行き、帰りにひろしまみなとマルシェに寄ってみる・・・炎天下の下、出店している人たちには脱帽ものです・・やはりお客は少なく営業的には苦しい・・・よしろう農園でしばらく雑談して帰宅、シャワーを浴びたらもう昼食
帰って月下美人を見ると昨晩に咲いていた・・残念見ることができなかった

内部監査支援システム開発
内部監査の指摘では、監査員の力量に左右されて的確な条項に基づく指摘が出来ていないのが実情である・・・今回、力量の不足をAIによって支援するシステムのモデルを構築する・・以下の課題は2点がメインだが、TAMの監査指摘4年分をデータ化し構造化することによって支援の形態が現実的に見えてきた
- AIに情報を渡すが、その情報が漏洩リスクとならないために、固有名詞などを送らせない
- 具体的な支援方法について、イメージが具体的にならない
内部監査システム構築のためのステップ
- STEP 1-1: 事実メモを箇条書きで入力(固有名チェックあり。通らないと進めない)
- STEP 1-2: AIが事実の不足を質問(最大3問×2ラウンド。スキップ可)
- STEP 1-3: 対話結果から事実文を自動文書化 → 監査員が修正・確定
- STEP 2: 条項候補Top-3+境界注記 → 選択または手入力
- STEP 3: ランク選択 → 指摘文案生成 → 修正
- STEP 4: 確定 → 事例DBに蓄積(次回のAI参照例に自動反映)
これまでに構築したもの
- [TAMの審査記録xlsx 4年分をデータ化してサンプルとする] : audit_case_extract(抽出+三段匿名化: パターン/辞書/ローカルLLM検査)
- [匿名化済み事例DB cases.csv 388件] :clause_bench(条項マッチング実力測定)
- [実測: ゼロショット85.5%/適合性系93.8% → RAGで88.1%・混同半減] :検討結果書(二層アーキテクチャ: 規格層=共通/流儀層=組織別)
- [audit_assist_proto(動くプロトタイプ)] :事実引き出し対話 → 匿名化ゲート → 条項候補 → 人間確定 → 事例蓄積(自己学習)
主要な実測値(仕様書の根拠数字)
- 条項マッチング(Top-3実務粒度): ゼロショット全体85.5% / 適合性系93.8%
- 粒度規約+TAM事例RAG(v2b): 全体88.1%、最大混同ペア(8.1↔6.1.2)半減
- ランク別定型句の対応(388件分析): 改善の機会=「推奨します」、観察事項= 「検討の余地があります」が相互汚染ゼロの完全分離 → 文章生成テンプレートに採用
- 適合性系(観察事項・懸念領域・改善指摘)と意見系(改善の機会・充実点)の 2群構造を確認 → ランクはAIが当てず、2分類推定+監査員選択の設計に
実地試用の状況と次回のTODO
済み: 2022年審査データで10件試用・・「力量ある監査員には良い指標」との評価・・記録済みデータ: confirmed_cases.csv・metrics.jsonl に実データ10件保持
次回確認すること:
- v1.1修正の適用確認(重要): v1.2完了報告にv1.1(過剰検知修正・許可ボタン・ ランク2分類化)の適用言及がない。「建築部」「工務課長」「2件の作業所」が ブロックされないか確認し、未適用ならv1.1指示書を先に適用させる
- 採用率18.2%の原因調査: 体感(「非常によくできている」、明確な条項誤りは1件)と 記録上の採用率18.2%が大きく乖離している。候補カードをクリックせず手入力で 条項を入れる操作習慣だと、候補が正しくても「手入力=不採用」と記録される。 metrics.jsonlの確定条項の生値と候補を突合し、指標定義の問題か候補品質の問題かを 切り分ける(次回セッションでmetrics.jsonlをアップロードすれば分析可能)
- 1.2の意地悪テスト: 最低品質のメモ(「・教育記録を確認 ・不十分」)への AIの質問が、TAMが新人に返す問いと一致するか 試用を10〜20件継続し、指標の推移を観察
暑い朝の散歩 ローカルLLM(Ollama)の構築

ローカルLLM(AI)の構築
ローカルLLMとして、Ollamaを選択、ローカルでOpenAI互換APIを提供、Laravelから通常のAPI呼び出しと同じ形式でローカルLLMを叩ける
インストールするWindowsPCは、・マザー ASUS ROG STRIX B550-A GAMING、CPU Ryzen9 3950X(16C32T 3.5-4.7GHz)、メモリ DDR4 PC4-28800 3600MHz 2✕32GB=64GB、グラフィックボード GeForce RTX™ 4070 Ti、M.2SSD PCle4.0 NVMe M.2 Kingston KC3000 1021GB、 PCIe Gen 4.0 x4 70000MB/Sで、GPUが少し不足気味だが、Ollama Qwen2.5 14B (Q4量子化 約9GB)が動きそうなのでインストールして試行する
Ollama本体のインストール
https://ollama.com/download/windows からOllamaSetuo.exeをダウンロード 実行してインストール、インストール後、Ollamaは常駐サービスとして起動します(タスクトレイにラマのアイコン)
NVIDIAドライバの確認
nvidia-smiを実行して、ドライババージョンとRTX 4070 Ti、VRAM 12288MiBが表示されればOK
モデルの取得と実行
ollama pull qwen2.5:14bをダウンロード完了したら、ollama run qwen2.5:14bで起動して、プロンプトから質問できる
GPU配分の確認
ollama psと入力して、OROCESSORが100%GPUとなっているので、VRAMに全部納まっている
API経由での動作確認(サーバ連携の予行)
Ollamaは自動的にhttp://localhost:11434でAPIを開いているので、Laravelから叩く検証ができる
月下美人とエスティマ整備
キクを散歩させて、眼医者に行き、青崎で気になっていたパン屋でモーニングを頂き、エスティマのオイル交換をする・・・7月末の信州旅行の準備

YouTubeのお勧め画面に、フランク・チャックフィールドの引潮があり、久しぶりにクリックして視聴、波の音とカモメの鳴き声、そして聞きなれたメロディ・・この曲は、中学1年の時に、父が初めてビクターのステレオを購入したとき、おまけで付いていたサンプルレコードに収録されていた曲、はじめて水主町にあった我が家でステレオを味わった
Jeepの車検
今朝も暑い、キクを連れて元宇品を散歩、キクはタヌキを見つける・・・走りすぎてバテてました・・・午前中に、J58の車検に、無事に終わって、今回はブレーキオイルを入れ替えたので¥5万程、昼からNGIさんが訪ねて来て久しぶりに雑談


J58車検準備 工事管理画面UXの実施
日赤の定期診断 CodeX(GPT-5.6 Sol)
今日は3か月ごとの定期診断と栄養指導で、広島日赤病院に朝から、血液を採取して診断、前回は血糖値が悪かったが、今回は改善していた・・夕食を減らして、体重を2㎏程減量した効果が出たようだが、クレアチンは少し高くなっていた・・まあ、ほとんど体調は変更なしということか

帰ってから、ログイン画面から会社概要への遷移が気に入らなかったので、修正して、会社概要ページを大幅に修正する・・ここに内部監査の計画及び実施状況をまとめる予定で、スペースを開けておく

Claude Fable5の試用期間が20日まで再び延長となった・・・OpenAIのGPT5.6のリリースで競争が激しくなった結果のようだ・・・GPT5.6はSol / Terra / Lunaのクラスがあり、Solは、Claude Fable5と同じ性能のようだ、GPT5.6のCodexはコーディング作業を支援する製品・エージェントという位置づけが明確になり、Claude Codeのプラグインとして使用できる
Claude Code(要件整理、設計、実装、リファクタリング)
Codex(セキュリティレビュー、バグ検出、性能改善)
さっそくClaude CodeにcodeX 5.6 solをプラグインで使えるように、指示してインストールを任せて、それと同時にChatGPTを無料版からPlusの有料版に切り替え、Claude CodeへのCodeXプラグインの設定は、便利なのもので調べる必要はなくすべてClaude Codeが以下のように実施してくれる
- Codex CLI更新: 0.130.0 → 0.144.4(GPT-5.6対応版)
- config.toml設定: C:\Users\syste.codex\config.toml の先頭に2行追記、model = “gpt-5.6-sol”、model_reasoning_effort = “medium”
- 既存の設定(プラグイン・trust設定)は無変更です
- 動作確認: テスト実行でヘッダーに model: gpt-5.6-sol / OpenAI Codex v0.144.4 を確認し、正常に応答が返りました
Claude Codeのcodexプラグインはモデル未指定時にconfig.tomlのデフォルトを使うため、今後 /codex:rescue やレビュー依頼はすべてSolで実行されます。推論の深さを変えたい場合は model_reasoning_effort を low / high に変更できます。
| /codex:rescue | メインの依頼コマンド。調査・修正・実装タスクをCodex(GPT-5.6 Sol)に委譲 |
| /codex:review | 現在の変更をCodexにレビューさせる |
| /codex:adversarial-review | より厳しい敵対的レビュー |
| /codex:status | 実行中ジョブの状況確認 |
| /codex:result | バックグラウンドジョブの結果取得 |
| /codex:cancel | 実行中ジョブの中止 |
| /codex:setup | CLI接続確認・設定 |
普段使いは /codex:rescue に続けて依頼内容を書くのが基本です。例:/codex:rescue 工程表の印刷でヘッダーがずれる原因を調査して
また、コマンドを打たなくても、会話の中で「これはCodexに調査させて」「Codexで直して」と指示してもらえれば、こちらからCodexエージェントを起動して結果を報告します。どちらでも同じSolが使われます
キクと散歩 工事一覧の変更
五日市埋立で散歩


4.結果
- mainマージ+本番デプロイ3回、すべて成功・稼働確認済み(最終コミット bd1cf1b)
- 自動テスト: 106件(うち5件失敗)→ 119件全パス(テスト14件新規追加・失敗0)
- 外形確認済み: セキュリティヘッダー出力・CookieのSecure属性・自己登録の閉鎖・診断ページの撤去
- 2026-07-11再検証の指摘は完了。システムは「Critical/High/Medium指摘ゼロ・依存脆弱性ゼロ(リスク受容2件は記録済み)」の状態
5.残課題(急ぎでない・別フェーズ)
- H-3: CSPのunsafe-inline除去(インラインJSの外部化 or nonce方式・大きめの作業)
- L-3: 同時編集ロックの精度向上(lock_version整数化)
- vite 4→8 メジャー更新(開発サーバー限定の脆弱性解消)
- x-data-spreadsheet(表エディタ)の代替検討 — XSS修正版が存在しないため。現状は同一会社内の編集権限者に限られるためリスク受容中
- 動作中の旧式遷移ボタン6箇所の data-href 方式への移行(1と同時に実施が効率的)
セキュリティ再検証・是正作業 全体総括
1.目的
システム全体を改めて検査(再検証)し、見つかった弱点を重要度順にすべて是正して本番に反映する
2.計画
4つの観点(認証・テナント分離・インジェクション対策・設定/依存関係)で並列監査を実施し、指摘を重要度別に整理 → Critical 0件・High 4件・Medium 9件・Low 9件・依存脆弱性多数・・・中核部分(認証・会社間のデータ分離・SQL/XSS対策)は基準適合と評価
| 区分 | 内容 |
|---|---|
| バッチ1 | 緊急度の高いもの:テンプレート操作の権限制限・AI生成HTMLのXSS対策・不要ファイル削除 |
| バッチ2 | 入力データの保存範囲固定・Cookie保護の既定化・セキュリティヘッダー補強・古いテストの整理 |
| バッチ3 | 依存パッケージの脆弱性解消・細かな改善9件(L-1〜L-9) |
| 確認事項5件 | 確認事項5件 |
3.実施
バッチ2
- 現場情報の保存を「検証済みの項目だけ」に固定 — 従来は細工したデータ送信で現場の所属会社を書き換えられる余地があった(調査中に登録処理側にも同じ問題を発見し、両方修正)
- セッションCookieのSecure属性を既定でON — 設定漏れがあっても自動的に安全側になる
- セキュリティヘッダー補強 — カメラ・マイク等のブラウザ機能無効化、クリックジャッキング・フォーム送信先の制限
- 実態と合わなくなっていた古いテスト5件を「現仕様の回帰検知」に書き換え
バッチ3
- 依存パッケージの脆弱性: composer 26件 → 0件(Excel処理ライブラリの重大な脆弱性含む)、npm 18件 → 4件(残りは開発環境限定等で影響なし・記録済み)
- パスワード変更・リセット時に他の端末のログインを即時無効化(乗っ取り後の締め出し対策)
- ファイル保存名のランダム化、デバッグ出力の削除、旧Gemini設定の廃止 ほか
確認事項
- 変更履歴(UserChangeLog): 会社間分離の仕組みを適用(設計どおり)
- 本番設定: 現地確認の結果、実は問題なし(APP_ENVは行なしでも本番扱い・GEMINIキーも本番には無かった)
- プロキシ設定: 診断ページを一時設置しTAMの実測で「前段プロキシなし」と確定 → IP偽装を許す設定を撤去
- 過去のAI生成データ: 一括洗浄コマンドを作成 → 本番で確認した結果、対象0件(すべて安全なデータのみ)
- 旧GeminiAPIキー: TAMがGoogle側で失効済み
元宇品の森を歩く ユーザー管理の検証
ユーザー管理検証
1.ユーザー管理・基盤是正の検証とリリース
今回反映された機能
- パスワードリセットのレート制限復活
- ログの日付別ファイル化(info・30日保持)※本番.envも書き換え済み
- パスワード強度10文字以上・英数字必須(日本語エラー)
- ユーザー無効化(is_active)+ログイン中セッション即時遮断
- 認証ログauth_logs(ログイン失敗・ロックアウト・無効化ブロック)
- 仮登録トークン72時間二段期限(承認時再セット)
2.検証中に発見・修正したmain由来バグ(3件)
検証したからこそ見つかった、以前から存在した問題:
- 新IPログイン通知メールが未捕捉 — メールサーバー障害時、初IPユーザーが全員ログイン500になるリスク → try-catch+警告ログ化
- 本登録リンクの無効/期限切れメッセージが非表示 — redirect(‘/’)経由でメッセージが捨てられていた → ログイン画面のメール欄下に表示
- パスワードリセット画面のルート喪失 — 「パスワードをお忘れですか」リンクが非表示になり機能の入口が無かった → ルート復活(既知テスト失敗も1件解消)
3.追加実施
- 認証まわりの日本語化: リセット画面・リセットメール本文・ログイン失敗/ロックアウトメッセージ(lang/ja.json・passwords.php・auth.php新設)
- パスワード変更専用ページ: 既存の/profileが導線ゼロで放置されていたのを発見。パスワード変更専用に改修し、ヘッダー右上に「PW変更」ボタンを設置。自己退会・自己情報変更はルートごと廃止(405)し、管理者経由+is_active無効化運用に一本化
4.検証で手間だった点と今後の改善
- メール確認: Mailtrap接続切れ→MAIL_MAILER=log化→メール本文がLOG_LEVEL=infoで消える、と二段のハマり。今後はローカル検証開始時にstorage/logs/mail.logの動作確認を最初にやる
- 「操作したつもりが反映されていない」事例が2回(更新ボタン未押下・ログイン済みウィンドウでのログイン試行)。検証はDBの記録とセットで確認するのが確実(今回はその方式で全件裏取りした)
- 419/500エラーは検証の中断ポイントになった。今後の検証手順書には「必ずCtrl+F5してから操作」を明記する
5.残課題(別起票)
- 既知テスト失敗5件(logout外部リダイレクト・パスワード確認・registration無効化×2・トップ302)
- script-srcの’unsafe-inline’除去(別フェーズ)
- フェーズ1候補: login_successのauth_logs統合・activitylog・SoftDeletes・uncompromised()・2FA
テスト基準(今後の比較用)
92パス / 5失敗(失敗はすべて上記の既知5件)。mainは 8e3b354
VFKさんが来る 建設アシスト 品質・セキュリティ改善 総括
朝は京橋川を散歩させて、シャワーを浴びて五日市の病院に、帰りに元宇品の森でキクを散歩させていたらVFKさんから電話、昼は近くの『はる』でお好み焼きを食べて、晩秋には北海道へJeepでキャラバンすることで盛り上がる・・・夕方に、贈り物がしたいということなので、洋酒の酒店に行く、ウイスキーが好みだそうで2種類を購入、TAMにも一本贈り物として頂いた

建設アシスト 品質・セキュリティ改善 総括
1.目的
建設アシストは、現場マネジメントDXの実践アプリケーションで、本プロジェクトの目的は以下の3点
- 大手組織のセキュリティ審査に耐えるシステムにする 複数テナント(会社)が同居するSaaSとして、テナント間のデータ分離を構造的に保証する
- AIに投げる情報の管理と漏洩リスクの低減 工事情報・現場情報をAI APIに送信する以上、何をどう送り、何を記録するかを一元的に管理できる構造にする
- 今後の機能追加に耐える保守性の確保 一人開発で継続的に機能を追加していくため、重複コード・デッドコードを排除し、「1箇所直せば全体に効く」構造を作る
2.出発点の課題(Fable 5による全体検証の結果)
セキュリティ(フェーズ1)
- Critical 7件・High 12件。中心はIDOR(他社データへの越境アクセス)で、工程表・安全パトロール・RA・施工計画書の主要機能に集中していた
- テナント分離がコントローラの手動認可(authorizeProject)に全依存しており、
1箇所の実装漏れがそのままデータ漏洩に直結する構造だった - 当時の評価:「現時点では大手組織のセキュリティ監査に耐えられない」
保守性(フェーズ2)
- AI呼び出しが8箇所に散在し、URL・タイムアウト・エラー処理がコピペ重複
- 工程表のJS約4,100行がBladeにインラインで埋め込まれ、CSP強化の障害に
- テナント設計が未完了のモデル(company_id未設定)が多数
- デッドコード(未完成のWord/Excel出力サービス、旧版施工計画書、孤立したAIサービス等)が大量に残存。
バグ(フェーズ3)
- 確定バグ14件。空CSVで法規制マスタが全削除される致命的バグ、工程表の無限ループ、祝日計算誤りによるCPMの1日ズレ等
- トランザクション欠落が主要機能に多数(途中失敗で中途半端なデータが残る)
- 同時編集の保護が皆無(後勝ち上書きで先の編集が無警告で消える)。
元宇品を散歩

その他の改善
- キャンバス表示範囲の拡張:工期ぴったりの表示から「工期の前後1ヶ月」に拡張。工期前後への工程配置が可能になり、読込時は工期開始位置へ自動スクロール。印刷は従来どおり指定範囲のみ
- 印刷範囲外工程の除外:バーチャートの印刷で範囲外の工程・接続線が出力される問題を修正。あわせてアノテーション(テキスト・フリー線)が印刷範囲変更時にずれる問題も修正(日付アンカー方式を導入)
- フリー線の太さ・矢印修正:太さ変更が即反映されない問題と、1pxで矢印が見えなくなる問題を修正(矢印を固定サイズに変更)
- ダブルクリック編集の修正:委譲化により発生した問題。DOM再構築のタイミング制御(requestAnimationFrame遅延・3px閾値)で解消
結果
| テスト | TenantIsolationTest 33件パス維持(全修正通じて) |
| 主な成果 | アノテーション機能の2画面統一・印刷品質の大幅改善 |
| 特記 | 印刷残像の根本原因はデバッグコードの消し忘れ1行だった |
工程表(バーチャート・ネットワーク)の品質改善
アノテーション機能の全面整備(メイン作業)
背景:2画面でアノテーション(テキストボックス・フリー線)の実装がバラバラで、barchartに欠けている機能が多かった・・設計書を作成してから4段階で実装した
| 1 | networkのイベント処理を委譲方式に統一(個別リスナー8箇所を撤去) |
| 2 | barchartにnetwork同等の機能を追加(ドラッグ移動・端点編集・描画プレビュー等) |
| 3 | UXルール統一(配置後即モーダル表示・ワンショット化) |
| 4 | 共通コード(schedules-common.js)として抽出・約230行の重複削減 |
あわせてモーダルのUI表記も両画面で統一(ボタンラベル・フォント選択肢・フリー線太さをselect化等)・・・P4完了後に発覚した退行(barchartのテキストボックス):長文・大フォントで文字が枠からはみ出し、クリック・ダブルクリックが効かなくなる問題。原因はforeignObjectの固定サイズ・・・networkにあった「文字量に合わせた自動拡大」が移植漏れだったため、共通モジュールに追加して解消
印刷機能の連続修正
| 問題 | 原因 |
|---|---|
| 印刷後に背面に残像が残る プレビュー表示中も残像が見える | try/finally未実装で復元処理が漏れる可能性 描画凍結中にpaintが完了しない |
| そもそも消えない | デバッグ用のコメントアウトが残ったまま |
| 月境界線が太すぎ・テキストの上に乗る | 旧レイアウト時代の「貫通線」が残存していた |
| 月境界線が「時々」途切れる | UTC変換による日付の1日ずれ(タイムゾーンバグ) |
楽観ロック実装
楽観ロックとは
複数ユーザーが同じデータを同時に編集した際、後から保存した人の内容が前の人の変更を上書きしてしまう問題を防ぐ仕組み
共通基盤の構築
4ファイルを新規作成して土台を整備
| ファイル | 役割 |
|---|---|
| ChecksOptimisticLock.php(トレイト) | サーバー側の照合・トランザクション・409返却 |
| optimistic-lock.js | フロント共通ミックスイン(トークン保持・競合処理) |
| conflict-modal.blade.php | 競合通知モーダル(退避DL・最新読込ボタン) |
| OptimisticLockTest.php | 検証テスト |
葡萄が実っている 工程表をJS外部化
梅雨明け宣言が出た広島だけど、あまり天気は良くない・・少しじっとしてあまり風も吹かない・・・今日は元宇品の森から海岸降りる道は、2カ所ともバリケードが設置してあり・・・海岸の遊歩道が山崩れでした・・・海岸線は誰1人いません・・いつもは釣りに人や散歩の人が多いんですが・・まぁのんびりとね海岸でキクを散歩させながら歩きます


工程表JS外部化
バーチャートと工程表のBladeファイルに数千行のJSがインライン記述されていた
| barchart.blade.php 2,439行 → 682行 |
| network.blade.php 3,083行 → 732行 |
| インラインJSを外部ファイルへ移設 約4,300行→1,414行 |
設計のポイント:
Blade側はJSON設定タグのみ残し、外部JSが読み込む方式を採用。これにより将来CSPのunsafe-inlineを除去できる構造になった
印刷用共通JS(518行)も共通モジュール化し、print-common.jsとして整理
着手前に工程表全体のモーダル構成を調査し、2画面間の実装差異(件数カウントのズレ・GW休日のデッドデータ等)も記録した(今回は修正対象外)
施工計画書「旧版」廃止(Phase 1・2)
長期間放置されていた旧版施工計画書のコードを2段階で削除
Phase 1:孤立コンポーネントとAPIルート4本を削除
Phase 2:本体を削除
| 削除対象 | 規模 |
|---|---|
| ルート | 13本削除 |
| コントローラメソッド | 8関数削除(960行 → 290行) |
| ビュー | フォルダごと削除 |
注意点:Phase 2着手直後にgetTemplateContentを誤削除していたことが判明(管理画面が使用中)→ 即座に復活させて修正・・本番データ(construction_plan_items 208件)はテーブルごと残置、コードのみ削除という方針で対応
PDF様式取込:sonnet vs haiku 品質比較
Step 8移行でPDF取込がhaiku→sonnetに変わったため、実際に品質を比較検証した
haikuの誤読は単純な省略ではなく意味の破壊で、施工計画書として実用不可レベル:sonnet維持を確定。PDF取込はセットアップ時の低頻度操作のため、コスト増の影響は限定的
成果まとめ
| 項目 | 内容 |
|---|---|
| コード削減 | インラインJS約4,300行を外部化・旧版コード約670行削除 |
| 品質検証 | PDF取込のsonnet採用を実データで根拠付け |
| テスト | TenantIsolationTest 33件パス維持 |
山口で仕事して、帰ってからコード修正
■昨日はグローバルスコープ化について、「親テーブル1段経由」だったが、「2〜3段経由」でテナント絞り込みが必要なモデル群の処理をする
| 系統 | 対象 | モデル数 |
|---|---|---|
| 系統1 | 監査木(指摘・是正処置・チェックシート系) | 5モデル |
| 系統2 | 工程表(ネットワーク・バーチャート系) | 4モデル |
| 系統3 | 施工計画(項目・画像・セクション) | 3モデル |
| 系統4 | 安全パトロール写真 | 1モデル |
■最終テスト結果:TenantIsolationTest 33件パス(46アサーション)
夕方に湯田温泉へ
建設アシストアプリケーションをマルチテナントSaaSとして「他社のデータは存在自体が見えない」状態を全モデルに実現する作業をする・・設計上の重要ポイントとして、グローバルスコープ単体ではなく、既存のIDOR(Insecure Direct Object Reference:URLのIDを書き換えて、他人のデータにアクセスする攻撃)対策トレイト(AuthorizesTenantAccess)と二重防御になっている。仮にどちらか一方に穴があっても、もう一方が守る構造で、これが大手組織のセキュリティ監査に耐えられる根拠になる
■会社IDを直接持つ主要モデル10個に、自動テナント絞り込みを適用
| 分類 | 対象モデル例 | 絞り込み方式 |
|---|---|---|
| 直接持ち | User, Project, Department など7モデル | WHERE company_id = 自社 |
| NULL=全社共通 | テンプレート・プリセット系3モデル | WHERE company_id = 自社 OR NULL |
■途中で発覚した重大問題と解決:User モデルにスコープを適用した直後、ログイン後の画面でメモリ枯渇エラーが発生・・・原因は無限再帰
■Project配下・監査計画配下のモデル13個に適用。これらは company_id を直接持たず、親テーブル経由で絞り込む
実データで確認した効果の例
| モデル | スコープ前 | スコープ後 |
|---|---|---|
| ProjectEnvAspect | 241件(他社75件含む) | 166件(自社のみ) |
| ProjectCondition | 49件(他社23件含む) | 26件(自社のみ) |
■最終状態
テスト:TenantIsolationTest 31パス(38 assertions) 対象:A分類10 + B分類13 = 計23モデル完了

Claude Fable5でシステムの検証
今日は雨の日曜日・・・現在最高性能を持つというAIのClaude Fable5が、6/1に提供されたが6/5には提供禁止となってしまった、7/1から再び提供されて、7/7まで使えるという・・・これは、是非とも一番課題で問題が多いシステム全体の成熟性を確認しなければ、熱も下がって少し調子も上がったので、さっそく取り掛かる
0.前提条件
- まずFable5には修正・削除・リファクタリングは一切行わなず検証を実施する
- 対応済みの事項は以下の内容(再確認は必要)
- AuthorizesTenantAccessトレイトによるコントローラのテナント認可
- SecurityHeadersMiddleware、HTTPS 強制、セッション強化、不審ログイン検知
- CSP 対応の途中経過(インラインイベントハンドラの addEventListener 化、@alpinejs/csp 採用)
1.作業フェーズ
- フェーズ1: セキュリティ検証(ファイル別)
- フェーズ2: 保守性・コード品質の改善提案(全体)
- フェーズ3: バグおよびバグの可能性の検出(全体)
2.フェーズ1: セキュリティ検証
2-1. 検証観点(チェックリスト)
A. テナント分離(最優先)
- クエリに tenant_id 等のスコープ漏れがないか(Eloquent 直接呼び出し、find($id)、DB:: 生クエリ含む)
- AuthorizesTenantAccess トレイトの適用漏れコントローラ・メソッド
- ルートモデルバインディングでの他テナントリソース参照可能性(IDOR)
- グローバルスコープの回避箇所(withoutGlobalScopes 等)の妥当性
B. 認証・認可
- ミドルウェア(auth, verified 等)の適用漏れルート
- Policy / Gate 未適用のまま操作可能なアクション
- 権限昇格の可能性(ロール判定の抜け)
C. 入力検証・インジェクション
- バリデーション未実施・不十分なリクエスト処理
- SQL インジェクション(whereRaw, DB::raw, DB::select 等の変数連結)
- マスアサインメント($fillable/$guarded の不備、$request->all() の直接渡し)
- パストラバーサル(ファイルパスにユーザー入力を使用している箇所)
D. XSS・出力エスケープ
- Blade の {!! !!} 使用箇所の妥当性
- SVG ダイアグラムエディタ(約3,600行の JS): ユーザー入力の SVG/DOM への挿入方法(innerHTML、属性直接代入等)、保存された SVG データの再表示時のサニタイズ
- リッチテキストバー(RTB)経由の HTML 挿入のサニタイズ
E. CSP 対応
- 残存するインラインイベントハンドラ(onclick 等)・インライン script/style
- SecurityHeadersMiddleware の CSP ディレクティブの妥当性(unsafe-inline / unsafe-eval の残存有無)
F. CSRF・セッション・Cookie
- CSRF 保護の除外ルート($except)の妥当性
- Ajax/fetch 呼び出しの CSRF トークン付与漏れ
- セッション・Cookie 設定(secure, httponly, samesite)と Xserver リバースプロキシ構成(TrustProxies)との整合
G. ファイルアップロード
- 拡張子・MIME タイプ検証、サイズ制限
- 保存先(public 直下への保存有無)、実行可能ファイルの拒否
- ダウンロード時のテナント認可
H. 情報漏洩
- ログ・例外メッセージへの機密情報出力
- .env 値のハードコード、デバッグコードの残存(dd, dump, console.log の機密出力)
- API レスポンスの過剰な属性返却(Resource 未使用でのモデル直接返却)
I. 依存パッケージ
- composer audit および npm audit を実行し、既知脆弱性を報告する(アップデートは実施しない)
3.フェーズ2: 保守性・改善提案
3-1. 検証観点
- 重複コード: コントローラ・JS 間の重複ロジック(サービスクラス / 共通モジュールへの抽出候補)
- 肥大化: 長大なコントローラメソッド・Blade ファイル・JS ファイル(特に SVG エディタ約3,600行の分割方針)
- 命名・構成: Laravel 標準構成からの逸脱、命名の不統一(日本語/英語混在の規則性含む)
- 設定のハードコード: config/env に逃がすべきマジックナンバー・文字列
- テスト: 自動テストのカバレッジ状況、テナント分離・認可まわりのテスト欠落箇所
- フロントエンド: Blade 内 JS の構造(モジュール化、イベント委譲の一貫性、Alpine.js との役割分担)
- DB: マイグレーションとスキーマの整合、インデックス欠落(tenant_id 複合インデックス等)、N+1 クエリ
- ドキュメント: CLAUDE.md / README の実態との乖離
4.フェーズ3: バグおよびバグの可能性
4-1. 検証観点
- 明確なバグ: 未定義変数・null 参照、型不整合、到達不能コード、条件式の誤り(=/==/=== 等)
- JS 側: SVG エディタのイベントリスナー解除漏れ(メモリリーク)、tblMergeCells/tblSplitCell 等テーブル操作の境界条件、undo/redo の状態不整合、非同期処理の競合
- 境界条件: 空配列・null・0件データ時の挙動、日付境界(年度・和暦処理があれば特に)
- トランザクション: 複数テーブル更新時のトランザクション欠落、失敗時のロールバック不備
- 並行性: 同一テナント内の同時編集での上書き・競合(楽観ロックの有無)
- 環境差異: MariaDB(ローカル)と MySQL(本番)の差異に起因する潜在問題、Xserver 固有設定への依存
- エラー処理: try-catch の握りつぶし、失敗時にユーザーへ誤った成功表示をする箇所
5.実行手順
- リポジトリ構成を把握する(app/, routes/, resources/views/, resources/js/, database/, config/, public/ を中心に全体を読む。vendor/, node_modules/ は除外)
- フェーズ1を実行し、レポートを出力して停止・確認を待つ
- 承認後フェーズ2を実行し、レポートを出力して停止
- 承認後フェーズ3を実行し、レポートを出力して完了報告
- 各フェーズの完了報告には「検証したファイル数」「読み飛ばした箇所とその理由」を必ず含める(検証の網羅性を判断できるようにするため)
F1.セキュリティ検証レポート(フェーズ1)
F1-1.検証規模
- コントローラ: 約40ファイル / モデル: 約50ファイル / Blade: 約168ファイル / ルート: 3ファイル / サービス: 8ファイル
- 検証観点: A テナント分離 / B 認証・認可 / C 入力検証・インジェクション / D XSS / E CSP / F CSRF・セッション / G ファイルアップロード / H 情報漏洩 / I 依存パッケージ
F1-2.指摘件数(重大度別)
| 数 | 主な内容 | |
|---|---|---|
| Critical | 7 | クロステナント IDOR 群(工程表・安全パトロール・RA・施工計画書)、CSP unsafe-inline + 保存型XSS の複合、phpspreadsheet SSRF/RCE |
| High | 12 | テンプレート認可欠落、機密ファイルの public 保存、保存型XSS(図面/AI-HTML/style属性)、依存パッケージ High、-tmp/_old ファイルのオートロード混入 |
| Medium | 15 | Mass Assignment、例外メッセージ露出、グローバルマスタ越境、パストラバーサル、Secure Cookie 未設定 等 |
| Low | 多数 | 多層防御・推奨改善(代表例+件数で集約) |
F1-3.総評
- 全モデルにテナント用グローバルスコープ(BelongsToTenant 等)が存在せず、テナント分離は各コントローラの手動 authorizeProject() に全面依存している。
- そのうえ authorizeProject() は「Project が自社か」しか見ず、ネストした子リソース(schedule / patrol / riskAssessment / item)の親一致を検証していないメソッドが多数あり、Route::scopeBindings() も未使用。結果として「自社の Project ID + 他社の子リソース ID」を URL に並べるだけで他テナントのデータを閲覧・改ざん・削除できる Critical な IDOR が7系統存在する。
- 加えて CSP に script-src ‘unsafe-inline’ が残存し、図面ノード・AI整形HTMLがサーバー側サニタイズなしで保存・再表示されるため、保存型XSSが現実的に成立する。
一方で、認可が正しく実装されているコントローラ群も多く(ProjectPlan / Audit 系 / CompanyAdmin など)、修正パターンは「authorizeProject() の追加 + 子リソースの親一致 abort_if の2行」と明確です。恒久対策として Route::scopeBindings() の全面適用とグローバルスコープ導入を行えば、監査耐性は大きく向上します。
F2.保守性・改善提案レポート(フェーズ2)
F2-1.テナント設計の未完了モデル洗い出し
重要な前提: 本アプリには BelongsToTenant 相当のグローバルスコープ(addGlobalScope)は1つも存在しない。テナント分離はすべてコントローラ内の手動 where(‘company_id’, …) / authorizeProject() に依存している。既存の booted()(BarTask / NetworkNode / NetworkArrow)は front_id(UUID)採番専用でスコープではない。したがって下表の「グローバルスコープ」列は全モデル「未実装」。
テナント到達経路: 子テーブルは company_id を持たず、project_id → projects.company_id(または schedule_id → schedules.project_id、audit_report_id → audit_plans.company_id 等)の多段リレーションでのみテナントを特定できる。
F2-2.観点: 重複コード
- 【高】Anthropic API 呼び出しの8重複(CLAUDE.md「AI推論は共通コード」ルール違反)
- 【高】テナント認可の二重方式(トレイトがあるのに手書きが残存)
- 【中】★ CSV入出力ロジックの6重複
- 【中】Docx/Xlsx出力の二系統併存(デッドコードの懸念)
- 【中】フロントエンド fetch/CSRF/モーダル制御の重複
F2-3.観点: 肥大化
コントローラ行数 Top10(実測)
| 数 | ファイル |
|---|---|
| 1548 | ConstructionPlanController.php |
| 952 | ProjectPlanController.php |
| 865 | NetworkScheduleController.php |
| 687 | SafetyPatrolController.php |
| 573 | EnvironmentController.php |
| 432 | RiskAssessmentController.php |
| 392 | BarChartController.php |
| 350 | ChecklistController.php |
| 313 | UserController.php |
| 251 | CompanyAdminController.php |
【高】Blade巨大ファイル(インラインJS肥大)
| 数 | ファイル | 特記 |
|---|---|---|
| 3082 | schedules/network.blade.php | 単一<script> が724-3080の約2356行 |
| 2439 | schedules/barchart.blade.php | 同様の巨大インラインJS |
| 1875 | projects_plan/edit_section.blade.php | @push(‘scripts’)+diagram-editor-script include+openCtxMenu上書きIIFE |
| 854 | environment/edit_environment.blade.php | |
| 729 | projects_plan/setup.blade.php | 対応 setup.js(392行)は分離済み=良い前例 |
- 提案: network / barchart の巨大インラインJS を resources/js/schedules/network.js・barchart.js に外部化(setup.js の前例に倣う)。CSP unsafe-inline 除去の前提条件でもある。
- 想定作業量: 大 → 別途計画が必要
【中】SVGダイアグラムエディタ群(実測 計4172行)の再分割
既に責務別5分割済み(良い設計)だが個別ファイルが肥大:
| 数 | ファイル | 責務 |
|---|---|---|
| 1541 | diagram-editor-nodes.blade.php | ノードCRUD/RTB/画像/線ノード |
| 1132 | diagram-editor-table.blade.php | 表/Excel貼付/xspreadsheet |
| 726 | diagram-editor-ui.blade.php | 右クリック/保存/ページ/テンプレ/印刷 |
| 602 | diagram-editor-connect.blade.php | コネクタ/接続線ダイアログ |
| 154 | diagram-editor-core.blade.php | 状態/Undo-Redo/グリッド |
風邪

さすがに風邪が酷いようなので、土曜日だが、耳鼻咽喉科の病院を探してゆく
かなり扁桃腺が腫れているので多くの薬をもらい、飲んで一日中寝込んでいる
薬が効いたのか、汗が出て少し気分は楽になった・・・夕方には、少し食欲もあり食事をして、また寝込む
防府から広島に
防府に出張
雨の7月
大河を散歩

甲斐犬のキクとの散歩は、旭町から西霞町に、ここから西本浦町に登り、団地を抜けて北大河から大河に下り、再び旭町に出て帰る・・何となく歩いていたら9000歩にもなった・・・甲斐犬のキクは最後は暑さでバテバテの様子(途中で2回水を飲ませたが)
今日は寝起きから喉が少し痛い・・・風邪かな、帰ってからは、なんとなく疲れたのか机でウトウト、何もせずに夕方になった
なんとなく湿気で体がべとべと、夕食前に入浴してすっきりした
J58フロントドライブシャフトブーツの交換
iPad Proの復旧
2020年4月に購入した、11インチiPad Pro 512GB Wi-Fi + Cellularモデル(iPad Pro11 第2世代)、もう6年間使用していることになるが、まだまだ現役で何の不自由もない・・ところが、大阪出張中に急にエラーが発生して、復旧不能となった・・・・Appleのサイトの手順に従って復旧を試みるが、復旧できない・・帰ってclaudeに相談して解決策を探ると、すぐ解決策を示してくれた
症状は、突如として復旧できないとのメッセージが出て、リセット→ リンゴマークが出る→長い間かかって→復旧の画面・・このiPadで問題が起きました→続ける→診断データ収集→Appleにデータ送信→パスワード入力要求→復旧できません→再起動:の繰り返し、となる・・・これは、ソフトウェアの深刻な損傷で、DFUモードからの復元が唯一の選択肢らしい
DFUモードの手順
事前準備
- MACminiに良質なケーブルでiPadを接続
- Finderを開いて待機
手順(タイミングが命)
- 音量上ボタン → 素早く押して離す
- 音量下ボタン → 素早く押して離す
- 電源ボタンを 10秒間押し続ける
10秒後、電源ボタンを押したまま → 音量下ボタンも同時に押す
そのまま 5秒間 両方押し続ける
5秒後、電源ボタンだけ離す(音量下は押し続ける) - さらに 10秒間 音量下を押し続ける
何回かチャレンジしてようやく成功・・・!!
成功すると:
- iPadの画面は真っ暗のまま(ロゴも何も出ない)
- Finderに「DFUモードのiPadを検出」と表示される
- これから、iPadにOSを再インストールする
長い時間がかかってOSの再インストールが終わりiPadは初期化されて復旧・・これから認証して、各種アプリケーションのセットをするが、iPhoneがあったので同期させて認証は楽だった
新大阪で研修
姫路から新大阪に
雨の姫路で仕事
今日は朝からかなりの雨が降っている
車で福崎の北の方の現場に一日中、ゆっくりと現場を楽しめた
姫路の思い出・・・神戸の現場で落ち込んでいたとき、1973年12月に姫路の新日鉄の広畑に配属され1994年8月まで・・現場のHiya所長には、大変かわいがってもらい、ここでかなり精神的にリカバリーができた・・・豪快な所長からは、はっきりと声を出せ、名前は枠いっぱいに大きな文字で書け、自信をもって何事も実施せよと教わり、これからの現場運営の大きな指針を与えられた・・現場にいた愛嬌があり元気だったお嬢と係員のKritとが、その後結婚したと聞いた・・・家は、姫路の北今宿に借り上げ社宅を借りていた
揖保川で安全担当の人からハヤ釣りを教えてもらったりした










































