今朝も暑い、キクを連れて元宇品を散歩、キクはタヌキを見つける・・・走りすぎてバテてました・・・午前中に、J58の車検に、無事に終わって、今回はブレーキオイルを入れ替えたので¥5万程、昼からNGIさんが訪ねて来て久しぶりに雑談


今朝も暑い、キクを連れて元宇品を散歩、キクはタヌキを見つける・・・走りすぎてバテてました・・・午前中に、J58の車検に、無事に終わって、今回はブレーキオイルを入れ替えたので¥5万程、昼からNGIさんが訪ねて来て久しぶりに雑談


今日は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が以下のように実施してくれる
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が使われます
今回反映された機能
検証したからこそ見つかった、以前から存在した問題:
92パス / 5失敗(失敗はすべて上記の既知5件)。mainは 8e3b354
朝は京橋川を散歩させて、シャワーを浴びて五日市の病院に、帰りに元宇品の森でキクを散歩させていたらVFKさんから電話、昼は近くの『はる』でお好み焼きを食べて、晩秋には北海道へJeepでキャラバンすることで盛り上がる・・・夕方に、贈り物がしたいということなので、洋酒の酒店に行く、ウイスキーが好みだそうで2種類を購入、TAMにも一本贈り物として頂いた

建設アシストは、現場マネジメントDXの実践アプリケーションで、本プロジェクトの目的は以下の3点
セキュリティ(フェーズ1)
保守性(フェーズ2)
バグ(フェーズ3)
建設アシストアプリケーションをマルチテナント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モデル完了

今日は雨の日曜日・・・現在最高性能を持つというAIのClaude Fable5が、6/1に提供されたが6/5には提供禁止となってしまった、7/1から再び提供されて、7/7まで使えるという・・・これは、是非とも一番課題で問題が多いシステム全体の成熟性を確認しなければ、熱も下がって少し調子も上がったので、さっそく取り掛かる
A. テナント分離(最優先)
B. 認証・認可
C. 入力検証・インジェクション
D. XSS・出力エスケープ
E. CSP 対応
F. CSRF・セッション・Cookie
G. ファイルアップロード
H. 情報漏洩
I. 依存パッケージ
| 数 | 主な内容 | |
|---|---|---|
| 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 | 多数 | 多層防御・推奨改善(代表例+件数で集約) |
一方で、認可が正しく実装されているコントローラ群も多く(ProjectPlan / Audit 系 / CompanyAdmin など)、修正パターンは「authorizeProject() の追加 + 子リソースの親一致 abort_if の2行」と明確です。恒久対策として Route::scopeBindings() の全面適用とグローバルスコープ導入を行えば、監査耐性は大きく向上します。
重要な前提: 本アプリには 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 等)の多段リレーションでのみテナントを特定できる。
コントローラ行数 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行)は分離済み=良い前例 |
【中】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/グリッド |
今週はほとんどの時間を施工計画書の再構築で費やした・・・自由に表や画像およびテキストをキャンバスに配置して、計画書をつくることは難しい・・・結局、色々試したが、使い慣れたVisio的な画面操作で作成することにした・・・作成はやはり、かなり難易度が高く、構築指示も何回も失敗したが、さすがにClaude Code、最後は何とか意図する内容にまとめてくれた
これから、実際に施工計画書を作成して、効果的なテンプレートをつくりながら、システムの使い勝手を検証してゆく

世界中のあらゆるサーバーはハッキング出来ると恐れられ、提供が中止されていたClaude Mythosに、安全フィルターが施されたClaude Fable 5が提供させるようになった・・・6/22まではトークンは消費(2倍)されるが、無料で使うことができるようになっていた・・・この間にシステム全体の診断をさせようと思っていたら、開始から3日目でUSAからの指示で提供が禁止(アメリカ国民以外は使用禁止・・だが、区別ができないので全世界で禁止となった)されてしまった・・・これからのAIの使い方に新しい波がやってくる予感

施工計画書 セットアップ画面 再構築
resources/views/projects_plan/setup.blade.php を中心に、セットアップ画面の右パネルを大幅改修・・・手直しではなく作り直しに
database/migrations/2026_06_13_000001_add_margin_to_project_plans_table.php
project_plans テーブルに余白カラムを追加margin_top(上余白 mm、デフォルト25)margin_bottom(下余白 mm、デフォルト25)margin_left(左余白 mm、デフォルト25)margin_right(右余白 mm、デフォルト20)
| メソッド | URL | 名前 | 用途 |
|---|---|---|---|
| PATCH | {plan}/settings| | project_plans.update_settings | 全体一括保存 |
| POST | {plan}/change-work-type | project_plans.change_work_type | 工事種別変更 |
| POST | {plan}/sections | project_plans.sections.store | セクション追加 |

| 変更 | 詳細 |
|---|---|
| edit_overview.blade.php | 削除 |
| routes/web.php | projects.overview.edit / projects.overview.update ルートを削除 |
| ProjectController | editOverview() / updateOverview() メソッドを削除 |
残留リンク確認: resources/views/projects/ 内に overview ルートへの参照なし(削除前にgrep確認済み)

変更前: <x-slot name=”nav_extra”> でヘッダータブとして表示
変更後*: 工事名・ステータスバーの右端にボタン配置
[ 工事名 (施工中) ] ··················· [ 部署: ○○ ] [ 担当: ○○ ] [ ✏️ 工事編集 ]

統合方法:
| 変更前 | 変更後 |
|---|---|
| create.blade.php(新規登録専用) | 削除 |
| edit.blade.php(編集専用) | create+edit 統合版に書き換え |

SafetyPatrolController.php saveDraft()メソッドshow.blade.phpのUIは$isLockedフラグで編集を無効化しているが、saveDraftエンドポイントにはis_finalizedチェックがなく、直接POSTで承認済みデータを上書き可能
修正
php
public function saveDraft(Request $request, Project $project, $id)
{
$this->authorizeProject($project);
$safetyPatrol = SafetyPatrol::findOrFail($id);
// 承認済みは変更不可 if ($safetyPatrol->is_finalized) { return response()->json([‘success’ => false, ‘message’ => ‘確認済みの記録は変更できません。’], 403); } //
| 項目 | 問題 | 対象箇所 |
|---|---|---|
| session(‘success’)表示 | CLAUDE.mdでは `toast.blade.phpは error のみ表示とあるが、`show.blade.phpに独自のsuccess表示が存在 | show.blade.php` L23-27 |
| ` 未使用 | 一覧のボタン群が直接 <button class=”bg-indigo-600…”>等で実装されている | index.blade.php` L43-53 |
| ファイル先頭の説明コメント欠如 | コントローラ・モデルの先頭に「このファイルの説明文」がない | SafetyPatrolController.php` 等全般 |
| インラインスクリプト | index.blade.phpの flash メッセージ消去処理がインライン<script>内に記述 | index.blade.php` L26-35 |
safetyPatrolController.php:210
php
// 現状:例外メッセージをそのまま返している
return response()->json([‘success’ => false, ‘message’ => ‘システムエラー: ‘ . $e->getMessage()]);
PHPの例外メッセージ(DBパス・APIキー名・内部構造等)がそのままフロントエンドに露出する
修正
php
// 固定文言に変更
return response()->json([‘success’ => false, ‘message’ => ‘システムエラーが発生しました。時間をおいて再試行してください。’]);
// ログには詳細を記録
\Log::error(‘AI checklist generation error: ‘ . $e->getMessage());
SafetyPatrolController.phpstore()
php
// 現状:バリデーションなしで直接 store()
$filePath = $request->file(‘attached_file’)->store(‘patrol_files’, ‘public’);
ファイルタイプ・サイズ制限がないため、実行ファイルや大容量ファイルのアップロードが可能な状態
修正
php
$request->validate([
‘attached_file’ => ‘nullable|file|mimes:pdf,jpg,jpeg,png,gif,webp|max:10240’,
‘patrol_datetime’ => ‘required|date’,
‘inspector_name’ => ‘required|string|max:100’,
]);
CLAUDE.md に「`onclick=””等のインラインハンドラを使わず、必ず `addEventListenerで登録する」と明記されているが、以下の箇所に違反が存在する
| ファイル | 行 | 内容 |
|---|---|---|
| show.blade.php | L105, L109, L113, L117 | onchange=”updateRowColor(…); autoSave()” |
| create.blade.php | L82 | onclick=”runAiProcess(…)” |
| index.blade.php | L43, L47, L51, L103, L115 | onclick=”window.location.href=…” |
修正方針:** 各ボタンに `data-url属性を付与し、外部JSで `addEventListenerに移行
SafetyPatrolController.php destroy()` メソッド
php
// 現状:attached_file_path のみ削除
if ($patrol->attached_file_path) {
Storage::disk(‘public’)->delete($patrol->attached_file_path);
}
$patrol->delete();
// → safety_patrol_photos テーブルのレコードと画像ファイルは残存
パトロール削除時に、紐づく写真ファイル(storage/public/patrol_photos/)とDBレコードが削除されない。時間とともにストレージを圧迫する
php
// 写真ファイルとレコードを先に削除
$patrol->safetyPatrolPhotos()->each(function ($photo) {
Storage::disk(‘public’)->delete($photo->file_path);
$photo->delete();
});
$patrol->delete();
朝から雨が降り続ける日曜日、娘たちを送って、また迎えに行く・・・今日はお隣が地鎮祭
建設にアップする画像の軽量化のルーチンを組み込んで、DBに取り込む画像の軽量化を図る

システム全体の画像アップロード処理を共通サービス化し、GDライブラリによる圧縮・リサイズを追加した
| コントローラー | メソッド | 最大 | ストレージパス |
|---|---|---|---|
| CompanyAdminController | uploadLogo | 5MB | company_logos/ |
| ProjectController | uploadPhoto | 50MB | photos/ |
| ChecklistController | uploadEvidence | 50MB | evidence/ |
| ConstructionPlanController | uploadItemImage | 5MB | plans/{id}/images/ |
| ConstructionPlanController | uploadTemplateImage | 5MB | templates/images/ |
| SafetyPatrolController | storePhoto | 10MB | patrol_photos/ |
以下は非画像混在・CSV等のため対象外とした:

法規制の特定を見直したので、同じような処理をしている環境側面の特定方法も修正する
今まで特定のための検索条件を工事概要から実施していたが、法規制の特定で作成した工事に関する条件DBを共有化、項目追加することに変更する・・・また、フロントエンドも法規制と同じようにする
| 質問 | 回答 |
|---|---|
| 条件保存方式 | project_conditions` テーブル新規作成。環境側面モーダルの条件も同テーブルに登録 |
| AI軽量化 | 今回は対象外。次のステップとして実施 |
| edit_overview の廃止範囲 | ☑ボックスで設定した内容を概要欄に転記する機能をすべて廃止。テキストボックスのみに変更 |
| @section(‘extra_tabs) | 環境側面編集画面のみで使用。他ページへの影響なし |
現在のファイルは3エリアで構成:
| エリア | 内容 | 対応 |
|---|---|---|
| エリア1(上部) | textareaとフォーム | 残す |
| エリア2(中央) | 「選択した項目を概要に追加する」ボタン | 残す |
| エリア3(下部) | チェックボックス群(工事種別・立地条件・工事規模・工事の特性・仮設設備等) | 削除 |


app/Models/Regulation.php ← $fillable 新カラム追加
app/Http/Controllers/ChecklistController.php ← 全面再構築
app/Http/Controllers/AdminController.php ← CSV新フォーマット対応
resources/views/components/eval_modal.php ← deleteEvidence URL修正
resources/views/layouts/footer.blade.php ← z-50 → z-10(モーダル被り解消)
routes/web.php ← conditionMatchルート追加・deleteEvidenceルート修正
法規制特定のコードの問題点が洗い出せたので、Excelシートをもう一度、見直しと再構築をして、いよいよコードを作成する

edit_Laws_Regulations.blade.phpとindex.blade.phpを指示書に従い全面再構築した
database/migrations/
2026_06_05_095137_add_select_columns_to_regulations_table.php
2026_06_05_095150_add_source_to_checklist_results_table.php
2026_06_05_112359_add_unique_index_to_checklist_results_table.php
app/Services/
RegulationMatcherService.php
resources/views/
components/laws_condition_modal.blade.php
Laws_Regulations/edit_Laws_Regulations.blade.php ← 新設計版
Laws_Regulations/index.blade.php ← 新設計版
Laws_Regulations/_tab_bar.blade.php ← 共通パーシャル

※課題:保存は全件DELETE → INSERT の洗い替え方式
| カラム | 型 | 役割 |
| project_id | FK | 現場 |
| regulation_id | FK | 法規制 |
| is_checked | boolean | 適用/非適用 |
c
法規制のコードを見直しを始めた・・・まずは現状分析
※課題:ai_description1列に「キーワード」と「制御フラグ」を混在させている
| カラム | 型 | 役割 |
| id | PK | — |
| parent_id | FK(self) | 親=null、子=親ID(2段構造) |
| group_code | string | 法律名(主に親) |
| ref_law | string | 関係条文(主に子) |
| action_conten | text | 実施すべき内容 |
| full_law_text | text | 原文(展開表示用) |
| ai_description | text | AI判定用キーワード(【選択必須】/【選択しない】制御フラグも兼用) |
| explanation_image | string | 解説画像 |
建設アシストの法規制管理の見直しを貸しする・・これで2回目となる
それなりに満足できる法規制の特定とはなっているが、もう一度判定に使っているAIを検討した結果、AIに頼らず、条件選定で多くが可能なことが分かってきたので変更を検討するが、今まで法規制の解釈のためにベースとなる体系(Excel→CSVで取込)を見直しをする必要ができてきた
2回目も、かなり突っ込んできたが、途中でかなり妥協をしていたので、今回は腰を入れて見直しを開始する・・・やはり、安衛法の解釈は複雑、言葉の定義から、法規制と思っていたのが実は「ガイドライン」だったり、新しい発見も多い・・・1日をかけて約半分まで終わったが・・・疲れる
ここで、もう一度「元請」周りの安衛法による定義を確認する
| 呼称 | 意味 | 根拠 |
| 事業者 | 労働者を使用する者すべて(元請も下請も) | 法2条3号 |
| 注文者 | 仕事を他人に請け負わせる者(下に出せば中間業者も注文者) | 法31条等 |
| 元方事業者 | 一の場所の仕事の一部を下請に請け負わせている事業者=元請(全業種共通) | 法15条1項 |
| 特定元方事業者 | 元方事業者のうち建設業・造船業(特定事業)のもの | 法15条1項 |
| 関係請負人 | 元方事業者の下のすべての請負人(一次・二次…下請全部) | 法15条1項 |
選任される「人」の呼称
| 呼称 | 誰が選任 | 役割 | 根拠 |
| 統括安全衛生責任者 | 特定元方事業者 | 現場全体の安全衛生を統括管理する人 | 法15条 |
| 元方安全衛生管理者 | 特定元方事業者 | 統括の管理事項のうち技術的事項を管理する人 | 法15条の2 |
| 店社安全衛生管理者 | 特定元方事業者(中小規模現場) | 店社(支店等)から現場を指導・巡視する人 | 法15条の3 |
| 安全衛生責任者 | 各下請(関係請負人) | 統括安全衛生責任者との連絡役 | 法16条 |
台風の接近で朝からかなりの雨です・・・甲斐犬のキクの散歩は予定通り、上下に登山用のレインコートを着込んで散歩、でも40年前のゴアテックスは効果が薄く、かなり浸み込んできました・・・やはり、新しいのを使わないと大雨は無理かな


環境側面であるコードのレビューを実施した
\environment\edit_environment.blade.php
\environment\index.blade.php
これが一番の地雷です。直近で@alpinejs/cspに移行してscript-srcから unsafe-eval を外したのに、1-1.この2画面はインラインイベントハンドラだらけonclick=”openAiModal()” / “closeAiModal()” / “runAiEstimate()”
onclick=”addCustomRow()” / “removeCustomRow(this)”
onclick=”window.print()”
script-srcからunsafe-inlineも外す方針なら、これらは全滅
Alpineだけ対応しても、素のonclickが残っていればCSPの一貫性は崩れる・・セキュリティ監査を目標にするなら、unsafe-inline除去は通過点になるはずなので、ここはaddEventListener方式へ統一すべき・・幸い既に477〜492行で同パターンを使っているのでdata-action=”open-ai-modal”のような属性+委譲リスナーに寄せれば機械的に直せる
so_app は、建設会社の作業所管理をシステム化した業務アプリケーションです。ISO監査・施工計画・環境側面・リスクアセスメント・安全パトロール・法規制管理を統合した、建設DXを目指した詳細な管理システム
| 項目 | 内容 |
| 技術スタック | Laravel(PHP) + Vite + Tailwind CSS + SQLite/MySQL |
| AI機能 | Claude API(法規制選定・環境側面推論・監査支援) |
| モデル数 | 約45モデル(ISO監査・工事管理・環境・安全・リスクなど) |
| 現在の状態 | 複数社でテスト運用中 |
| 目標 | 建設業界のDX化 |
| 特徴 | セキュリティを重視した「統制下でのAI活用」の実証システム |
| 作業 | 状態 |
| セキュリティ監査(Critical 1〜4 テナント分離) | ✅ 完了 |
| セキュリティ監査(High 7〜9 認可漏れ) | ✅ 完了 |
| AI送信情報のガード機構(InputValidator) | ⏳ 次タスク |
| AI送信内容の透明性確保(ユーザー画面への明示) | ⏳ 予定 |
| Medium 13 ファイル名処理 | ⏳ 予定 |
| 今後作業 | 効果 |
| Blade コンポーネント化(写真・添付・印刷UI) | 新機能追加が高速化 |
| AI Service の共通基底クラス | AI呼び出しの一元管理 |
| PrintHelper・共通ヘルパー関数の整備 | 重複コードの削減 |
| トレイト化(HasPhotos, HasAttachments等) | モデルの統一化 |
| Policy への移行(Phase 3) | 認可の構造的解決 |
| グローバルスコープによるテナント自動分離 | 忘れて漏れる事故の防止 |
| 作業内容 | 対象ファイル | 状態 |
| InputValidator の実装(AI送信ガード機構) | app/Services/Ai/InputValidator.php | ⏳ |
| 既存AI Serviceへの組み込み(5箇所) | AiRecommendationService等 | ⏳ |
| Environment + RiskAssessmentへのトレイト確認 | 完了確認 | ✅ |
| ai_usage_logs テーブルの設計・作成 | database/migrations/ | ⏳ |
| プロンプトキャッシュの実装 | 全AI Service | 📅 |
| ログローテーション設定(.env変更) | config/logging.php | 📅 |
このシステムは「技術者が作った業務システム」ではなく、「業務実践者がAIを道具として使って作った業務システム」です。建設業界のDX化に向けて、特に以下の点で先進的な位置付けにあります
今AIの活用に伴い、AIのセキュリティが大きな課題となっていますが、「AI使用禁止」ではなく、「適切な制御下での活用」という選択肢を具体例として示すことが目標とし、このシステムが業界全体のAI活用推進のモデルケースとなることを目指します
| 今後作業 | 期待効果 |
| AI利用ログテーブル(ai_usage_logs)の実装 | コストの可視化・会社別分析 |
| コスト制御(予算上限・アラート)コスト制御(予算上限・アラート) | APIコストの自動管理 |
| ルールベース匿名化サービス | 機密文書の安全なAI活用 |
| セキュリティ監視Console Command | 日次自動チェック |
| セキュリティダッシュボード | 運用状況の可視化 |
| プロンプトキャッシュの実装 | APIコスト最大90%削減 |
| 今後作業 | 内容 |
| Ollama + ローカルLLMの検証 | 自前AIの感触をつかむ(無料) |
| 契約書・技術文書の匿名化処理 | 機密情報を外部に出さない仕組み |
| 統合AIパイプライン | 匿名化→外部AI→復元の一連の流れ |
| AI利用の完全監査ログ | セキュリティ監査員AI |
| 管理ダッシュボードの高度化 | リアルタイム監視・異常検知 |
| 今後作業 | 内容 |
| サーバーセキュリティの強化 | ファイアウォール・HTTPS・バックアップ |
| ユーザー管理のセキュリティ強化 | パスワードポリシー・2FA・セッション管理 |
| スケーラビリティ対応 | 複数社本格導入への対応 |
| SLA・サポート体制の整備 | 商用化に向けた運用体制 |
| 項目 | 内容 | 優先度 |
| パスワードポリシー | 複雑性要件・有効期限の設定 | 高 |
| ログイン試行回数制限 | ブルートフォース攻撃対策 | 高 |
| セッションタイムアウト | 一定時間後の自動ログアウト | 高 |
| 退職者の即時無効化 | アカウント無効化フローの整備 | 高 |
| 二要素認証(2FA) | 重要操作時の追加認証 | 中 |
| アクセスログ閲覧UI | 管理者向けの操作履歴確認機能 | 中 |
| 項目 | 内容 | 難易度 |
| HTTPS の徹底 | SSL証明書の設定・自動更新 | 低 |
| 不要ポートの閉鎖 | ファイアウォール設定 | 中 |
| OS・PHP・Laravelのアップデート方針 | 定期更新のルール化 | 低 |
| バックアップ体制 | 自動バックアップの設定・復旧手順 | 中 |
| ログローテーション | 日次ローテーション設定(保存14日) | 低 |
| 依存ライブラリの脆弱性チェック | composer audit の定期実行 | 低 |
SaaS運用に向けたセキュリティ強化として、フェーズ1(必須項目)の完了およびフェーズ2の主要項目を実装した。
結果
本番・ローカル各.envに以下を追記:
| 項目 | 本番 | ローカル |
| SESSION_SECURE_COOKIE | true | false |
| SESSION_ENCRYPT | true | true |
| SESSION_SAME_SITE | strict | lax |
結果
app/Http/Requests/Auth/LoginRequest.php を確認した結果、Laravel標準のRateLimiterによる以下の機能がすでに実装済みであることを確認した。
結果
app/Http/Middleware/SecurityHeadersMiddleware.phpを新規作成し、bootstrap/app.php` に登録。
設定したヘッダー:
| ヘッダー | 設定値 | 効果 |
| Strict-Transport-Security | max-age=31536000 | HTTPS強制をブラウザに記憶 |
| X-Frame-Options | DENY | クリックジャッキング防止 |
| X-Content-Type-Options | nosniff | MIMEタイプ誤判定防止 |
| Referrer-Policy | strict-origin-when-cross-origin | URL漏洩防止 |
| Content-Security-Policy | self + unsafe-inline | XSS対策 |
注意事項
app/Http/Middleware/SecurityHeadersMiddleware.hpを新規作成し、bootstrap/app.php` に登録。
設定したヘッダー:
| ヘッダー | 設定値 | 効果 |
| Strict-Transport-Security | max-age=31536000 | HTTPS強制をブラウザに記憶 |
| X-Frame-Options | DENY | クリックジャッキング防止 |
| X-Content-Type-Options | nosniff | MIMEタイプ誤判定防止 |
| Referrer-Policy | strict-origin-when-cross-origin | URL漏洩防止 |
| Content-Security-Policy | self + unsafe-inline | XSS対策 |
注意事項
新しいIPアドレスからのログインを検知し、登録メールアドレスへ通知メールを自動送信する機能を実装。
新規作成ファイル
app/Mail/SuspiciousLoginMail.php
resources/views/emails/suspicious_login.blade.php
resources/views/emails/suspicious_login_text.blade.php(HTML/テキスト両形式対応)
修正ファイル
app/Http/Controllers/Auth/AuthenticatedSessionController.php
検知ロジック:
$isNewIp = !LoginLog::where(‘user_id’, $user->id) ->where(‘ip_address’, $request->ip()) ->where(‘id’, ‘!=’, $log->id) ->exists(); if ($isNewIp && $user->email) { Mail::to($user->email)->send( new SuspiciousLoginMail($user, $request->ip(), now()->format(‘Y年m月d日 H:i’)) ); }
メール設定
| 環境 | 設定 |
| 本番 | Xサーバ SMTPサーバ(sv13426.xserver.jp:587) |
| ローカル | MAIL_MAILER=log(ログファイルに出力) |
動作確認結果
残課題
MSN/Outlookの迷惑メール判定を解消するため、DNSへのSPFレコード追加を推奨。
レコード種別:TXT
値:v=spf1 include:xserver.jp ~all
| 項目 | 状態 |
| パスワードのハッシュ化(bcrypt) | ✅ 完了(実装済み確認) |
| HTTPS強制 | ✅ 完了 |
| セッションのセキュア設定 | ✅ 完了 |
| ログイン失敗のロック機構 | ✅ 完了(実装済み確認) |
| 項目 | 状態 |
| セキュリティヘッダー(HSTS等) | ✅ 完了 |
| 不審ログイン通知メール | ✅ 完了 |
| SPF・DKIMの設定 | ⬜ 未対応(推奨) |
| パスワードリセットフローの強化 | ⬜ 未対応(次回 |
iso_app (建設アシスト)のセキュリティ強化を実施する
Claude Code(Opus 4.7)を「セキュリティ監査員」として起用し、以下の観点でアプリケーション全体を調査しました。
| 重大度 | 件数 | 対応状況 |
| Critical | 6件 | 4件完了・2件対応中 |
| High | 8件 | 7件完了・1件対応中 |
| Medium | 2件 | 計画中 |
| 合計 | 16件 | 11件完了 |
| 項目 | コントローラー | 内容 | 状態 |
| 認可漏れ | ChecklistController | getEvidence で他社データをJSON取得可能 | ✅ 完了 |
| 認可漏れ | EnvironmentController | index/edit/save/aiEstimate でテナント確認なし | ✅ 完了 |
| 認可漏れ | RiskAssessmentController | downloadAttachment で他社ファイルダウンロード可能(16メソッド) | ✅ 完了 |
| AI情報 | AuditAiService | 被監査対象名・業務概要がAPI送信される | ⚠ 対応中 |
| AI情報 | SafetyPatrolController | 作業内容・使用機械の詳細が送信される | ⚠ 対応中 |
| AI情報 | risk_assessment.blade.php | 下請業者名・プロジェクト名がプロンプトに含まれる | ⚠ 対応中 |
認可ロジックを一元化する AuthorizesTenantAccess トレイトを作成しました。
app/Http/Controllers/Concerns/AuthorizesTenantAccess.php
このトレイトにより:
| コントローラー | 保護メソッド数 | 対応回 |
| ProjectController | 8メソッド | 第1回 |
| ConstructionPlanController | 15メソッド | 第1回 |
| SafetyPatrolController | 14メソッド | 第1回 |
| ChecklistController | 6メソッド | 第1回 |
| EnvironmentController | 4メソッド | 第2回 |
| RiskAssessmentController | 16メソッド | 第2回 |
| 合計 | 63メソッド | ー |
各コントローラーに対して以下のパターンを網羅的にテスト:
| 項目 | 内容 |
| 実施時間(合計) | 約2時間半 |
| API利用コスト | $6.51(約1030円) |
| 外注した場合の市場価格 | 130〜350万円相当 |
| コスト比 | 約1300〜3500倍の費用対効果 |
| コード変更量 | 673行追加、12行削除 |
| テスト件数 | 26件 全PASS |
最も重大な問題でした。URL のIDを変えるだけで他社のデータに読み取り・編集・削除アクセスが可能な状態でした
| 対象コントローラー | 影響範囲 | 重大度 |
| ProjectController | show/edit/update/destroy/editOverview/updateOverview/uploadPhoto(8メソッド) | Critical |
| ConstructionPlanController | downloadDocx/downloadXlsx/generatePdf/diagramEditor等(15メソッド) | Critical |
| SafetyPatrolController | create/store/index/show/destroy/generateAiChecklist等(14メソッド) | Critical |
| ChecklistController | deleteEvidence/getEvidence等(6メソッド) | Critical |
発注者名・予算・下請業者名・近隣企業名などが、マスキングなしで Anthropic Claude API に送信される可能性がありました。
【現状の評価(設計意図の確認後)】
現状のAI利用は「チェックボックス選択による固定語彙のみを送信」という設計になっており、実質的な機密情報漏洩リスクは低い状態です。ただし、将来の機能拡張で誰かがフリーテキストを送る実装をしてしまうリスクの予防として、コードレベルのガード機構を実装予定です。
| フェーズ | 内容 | 状態 |
| Phase A | リスクアセスメント(自主監査) | ✅ 完了 |
| Phase B-1 | Critical 1〜4 テナント分離 | ✅ 完了 |
| Phase B-2 | High 7〜9 認可漏れ(Environment, RiskAssessment) | ✅ 完了 |
| Phase B-3 | Critical 5〜6, High 10〜12 AI関連 | ⏳ 次フェーズ |
| Phase B-4 | Medium 13 ファイル名処理 | ⏳ 後ほど |
| Phase C | AIゲートウェイ構築・匿名化 | 📅 来月 |
| Phase D | 監視・運用体制の確立 | 📅 数ヶ月後 |
| Phase E | 継続的改善(PDCA) | 継続 |
現在の「固定語彙のみ送信」という設計意図をコードで強制するバリデータークラスを実装します。
契約事項・技術的背景・経営内容の文書化を扱う際、自前サーバーに置いたローカルAIで一般化処理をしてから外部AIに送信する仕組みを構築予定です。


建設アシストのコードが多くなってきたので、Claude Codeのトークン消費が多くなってくる(毎回、コードを読み込んで応答するため)・・・2日ごとにクレジット要求が来るようになったので、今噂のchatJPのClaude Code向けのプラグインであるCodexをインストールをして、さっそく工事管理のフロントエンドを修正させたが、ずいぶん時間がかかり、おまけにClaude codeも消費しているようで、またクレジットが切れてしまった・・・いくら請求が来るのか戦々恐々・・・Codexが使えるようであればFreeから契約するかと思っていたが、もう少し様子をみる必要がある・・・・Claude Codeを使わなくても、Clude,Geminiなどでもコード作成はできるが、スピードとシステム全体の網羅性はClaude Codeを使いだすと数倍以上に効率が良いため、中々戻れない

朝から少しづつ降り出した雨は、昼頃から本降りの雨となって夜半まで降り続く・・・朝は、キクと元宇品の森を散歩で歩く、日曜日なのでマラソンする人や、犬の散歩など多くの人が来ていて、灯台の駐車場は満車の状態・・・散歩の帰りには、ガソリンが警告灯が付いたので、四国の旅行で給油したときから給油していない・・忘れないうちにスタンドで給油、まだガソリンは¥157と安かった
昼前に買い物に行き、明日の厨房の大工仕事のため、木材を購入する
昼からは、ネットワーク工程表のアプリケーションを作成する・・・やはりネットワーク工程表は中々難しいが、Claudeが手助けしてくれるが、難しい依頼はトークンの消費が激しく、クレジットの要求がすぐ来るので、使い方は考えながらする必要がある
夕方には、ほぼ納得できるような工程表が作れるアプリケーションが出来上がった・・・実際に入り色な工程を作成して調整してゆく必要があるが、問題は印刷のスケールをどのように調整するかが当面の課題、ネットワークがうまく表現できない


きょうから少し天気は下り坂
建設アシストも予定していたメニューは、ほぼ出来上がったので、各ページにHelpのモーダルをつくり、使い方などの説明を書いてゆく
それに合わせて、動きやメニューボタンの配置など細かな操作部分の改修を行ってゆく・・・地味な作業だが、これが重要・・・・しかし、割と単調なので疲れてしまう
AIの選定の調整も重要なので、条件を変えて確認する