年: 2026年
五日市埋立で散歩


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とが、その後結婚したと聞いた・・・家は、姫路の北今宿に借り上げ社宅を借りていた
揖保川で安全担当の人からハヤ釣りを教えてもらったりした
夕方から姫路に
雨のみなと公園
横川で仕事
キクと元宇品

2.onclick / onchange インラインハンドラを addEventListener に移行する
サーバー側のバリデーション・サニタイズと、ブラウザ側のCSPの両方が必要
- グループA:サイドバー(id 付き → そのまま addEventListener)
- グループB:サイドバー(id なし → id を付与してから addEventListener)
- グループC:ページタブバー(id なし → id 付与)
- グループD:ナビバー(Blade 条件分岐内)
- フローティングRTB(書式ツールバー)のインラインハンドラ移行
施工計画のエディット画面(edit_section_blade.php)が、ほぼ実装が完了したので、再びコードの検証を行う・・・やはり、まだ課題が多く残っていたので、順にコードの手直しをする
1.生HTML出力({!! !!})を使用している
{!! !!} はエスケープなしの生出力のため、$headerHtml / $footerHtml がDB経由で、悪意あるスクリプトを含む場合、XSS攻撃が成立する。
サーバーサイドでのサニタイズ(無害化)状況を確認し、不十分であれば修正する・・・XSS(クロスサイトスクリプティング)、SQLインジェクション・・以下はサニタイズの手法
| 手法 | 内容 |
|---|---|
| エスケープ | 特殊文字を無害な表現に変換(< → <) |
| 除去 | 危険な文字・タグを削除 |
| バリデーション | 想定外の値を拒否(数字のみ受け付けるなど) |
| プレースホルダ | SQLをコードと分離して処理 |
これらの手法は、Laravelでは多くは自動で処理してくれるが、施工計画のSVGダイアグラムエディタのような自前JS処理部分は別途確認が必要
1-1.データの流れを追跡する
- コントローラを特定する(ルート名 project_plans.sections.editから逆引きする)
- $headerHtml / $footerHtml の生成箇所を特定する
- DBカラムの確認
1-2.現状の判定(サニタイズ処理必要性の検証)
- ✅ 安全なケース(修正不要)
- ❌ 要修正なケース(対応する、入力時サニタイズ、HtmlPurifier の導入確認、サービスクラスまたはヘルパーの作成、コントローラの保存処理にサニタイズを追加、既存DBデータの一括サニタイズ(Artisan コマンド))
1-3.実施結果
Claude Codeでの実施結果ではOK、変更なし、コメントを追記
五日市の埋立地 施工計画エディタ画面修正
J58のパーツが届く 施工計画の全面修正
土曜日だが、朝から一日雨がℎぐり続く・・・まあ、梅雨だから当たり前だが、キクの散歩はみなと公園・・・一日中、施工計画の改修


施工計画書作成のエディタ分析(diagram-editor-script)
- 完全自作図面エディタエンジン
- 174関数 / 3,686行 / 166KB、→ 単一ファイルとしては限界に近いサイズ
- 外部ライブラリなし、SVGとdivだけでDrawio・Visioのような図形編集を自力実装
| 観点 | 評価 |
|---|---|
| コード品質 | セクション分けが明確で追いやすい |
| 機能完成度 | 商用ツールに近いレベル |
| CSP対応 | 95%完了・ページタブのみ残存 |
| データ設計 | JSON構造が明確で拡張しやすい |
| リスク箇所 | renderPageTabs()のinline onclick |
リファクタリングの優先順位
| 優先 | 内容 | 効果 |
|---|---|---|
| 🔴 高 | getTargetId()関数を1つ作りID取得を統一 | バグ防止 |
| 🔴 高 | setBg()をapplyBoxBg()に統合 | 重複解消 |
| 🔴 高 | toggleBorder()をapplyNodeBorderToggle()に統合 | 重複解消 |
| 🟡 中 | ctx系をコア関数に引数追加で統合 | コード削減 |
| 🟡 中 | tbl系を別ファイルに切り出し | 見通し改善 |
| 🟢 低 | snapshot()をラップして自動呼び出し化snapshot()をラップして自動呼び出し化 | 呼び忘れ防止 |
渡川ダムに 夜遅く広島に帰る
北浦漁港へ
日向市に出張
たっぷりある時間の中で、Claudeと肥大になった施工計画の作成画面について分析を実施してもらう・・・サーバからコードをダウンロードして、iPadなどでちょっとやりにくいが、Claudに読ませる・・色々と改善案を提案して、三つの改善指示書を作成してくれる・・・特急にちりんは、もうすぐ延岡に、外はいつの間にか雨となっている

宮崎までの日豊本線は長い、大分からは単線で延岡までは、曲がりくねった山の中をのんびりと走る
特急日輪は、宮崎空港まで直通の貴重な列車・・ほとんどは大分で乗換



宇品みなと公園

施工計画書の表紙と目次の編集機能の整理
計画書のヘッダーとフッターの編集機能、また表示がおかしいことの修正,、余白の調整・・まだまだ、改善すべきところは多い
しかし、最近どうもClaude Codeの切れが悪い・・・コードが肥大化したかな、整理を考える必要がある

J58を修理工場に
今週は天気が悪くなるとのことだが、良い天気の月曜日、朝は久しぶりに元宇品の森を歩く・・・最近は、森のアップダウンの散歩は辛くなってきている、午前中は今週の仕事の段取りをして、昼からはキクを助手席に乗せてJ58を修理工場に移送
最近は旧車を修理してくれる修理工場が無い、昔の車の修理はわからないそうだ・・・いつもの修理工場に無理を言ってお願いする、パーツがあればとのことなので、パーツリストからパーツを頼むが、あっているか少し不安、パーツも中々高価で、失敗すると痛手が大きい、修理の期限は付けないが7月中には終わらせてもらいたい















































