diff --git a/.agent/PLANS.md b/.agent/PLANS.md index 648a12f29..55f7bf3b6 100644 --- a/.agent/PLANS.md +++ b/.agent/PLANS.md @@ -56,7 +56,9 @@ ExecPlan の仕様書。複雑なタスクはこの仕様に従い `.agent/plans - 実装精度と再現性を維持したまま簡潔に書き、同一趣旨の重複記述を避ける - 長大なコード全文の貼り付けは原則避け、対象箇所・変更意図・確認コマンドを優先する - 次のマイルストーンへ自律的に進む(「次は?」と確認しない) -- 完了した ExecPlan は削除せずナレッジとして残す +- 完了した ExecPlan は `.agent/plans/archive/` へ移動する +- アーカイブ時はファイル名先頭の日付を完了日(`YYYY-MM-DD`)へ更新する +- ロードマップに `ExecPlan:` を記載している場合は、移動後のパスへ更新する ## 成功基準 diff --git a/.agent/plans/2026-02-14-api-router-foundation.md b/.agent/plans/2026-02-14-api-router-foundation.md new file mode 100644 index 000000000..efd4ddac4 --- /dev/null +++ b/.agent/plans/2026-02-14-api-router-foundation.md @@ -0,0 +1,105 @@ +# ExecPlan: API Router基盤の先行構築(Phase 0) + +## Purpose / Big Picture + +REST API実装の前提として、`api.php` に集約されるルーター基盤を先行実装し、後続の認証・read・write実装を安全に分離して進められる状態を作る。これにより、機能追加時の分岐肥大化を防ぎ、API全体の拡張性と保守性を確保する。 +中長期的には、フロント・管理画面・APIを単一フロントコントローラへ統合するための足場として扱う。 + +## Progress + +- [ ] (2026-02-14) ルート定義フォーマットを確定する +- [ ] (2026-02-14) ルート登録レジストリを実装する +- [ ] (2026-02-14) `method + path` ディスパッチャを実装する +- [ ] (2026-02-14) namespace省略解決(`/api/v1/...` -> `/api/evo/v1/...`)を実装する +- [ ] (2026-02-14) 404/405/OPTIONSの標準応答を実装する + +## Surprises & Discoveries + +- 既存CMSにはルーティングの明示レイヤーがなく、実装箇所の分散が起きやすい。 + +## Decision Log + +- 2026-02-14 / AI / Routerは独立Phaseで先行し、後続Phaseの共通土台とする。 +- 2026-02-14 / AI / `GET /api/v1/...` は本体API省略形として解決する。 +- 2026-02-14 / AI / WordPressは構造設計の参考にするが、互換目的の制約は導入しない。 +- 2026-02-14 / AI / 本RouterはAPI専用に閉じず、将来の「管理画面URL変更機能」で再利用できる設計にする。 +- 2026-02-14 / AI / 当面は `api.php` 先行導入で段階移行し、最終的に単一エンドポイント運用へ寄せる。 + +## Outcomes & Retrospective + +実装後に記載 + +## Context and Orientation + +用語: + +- ルートレジストリ: ルート定義(namespace/version/path/methods/callback)を保持する仕組み。 +- ディスパッチャ: 受信リクエストを一致ルートへ振り分ける処理。 + +対象ファイル: + +- `api.php` +- `manager/includes/rest-api.inc.php` +- `manager/includes/rest-routes.php` + +## Plan of Work + +まずルート定義・登録・解決の責務を固定し、認証やビジネスロジックとは分離する。Router層は純粋に経路解決と標準HTTP応答に集中し、認証・レート制限は後続Phaseでミドルウェアとして接続する。これにより段階実装時のリスクを抑える。 +あわせて予約パス(`/api/`, `/manager/`)の優先順位ルールを定義し、将来の管理画面URL変更時に同じ解決ルールを使えるようにする。 +移行期は既存エンドポイントとの互換を維持し、運用が安定した段階で単一フロントコントローラへ統合する。 + +## Concrete Steps + +1. ルート定義APIを作る。 + 編集対象ファイル: `manager/includes/rest-api.inc.php` + 実行コマンド: `php -l manager/includes/rest-api.inc.php` + 期待される観測結果: `register_rest_route()` 相当が利用できる。 +2. ディスパッチャを作る。 + 編集対象ファイル: `manager/includes/rest-api.inc.php` + 実行コマンド: `rg -n "dispatch|405|404|OPTIONS" manager/includes/rest-api.inc.php` + 期待される観測結果: ルート未一致404、メソッド不一致405、OPTIONS応答が実装される。 +3. `api.php` をフロントコントローラ化する。 + 編集対象ファイル: `api.php` + 実行コマンド: `php -l api.php` + 期待される観測結果: ルーティング処理が単一入口に集約される。 +4. 省略namespace解決を追加する。 + 編集対象ファイル: `manager/includes/rest-api.inc.php` + 実行コマンド: `rg -n "/api/v1|/api/evo/v1|namespace" manager/includes/rest-api.inc.php` + 期待される観測結果: `/api/v1/...` が `/api/evo/v1/...` と同等に解決される。 +5. 予約パス優先順位ルールを定義する。 + 編集対象ファイル: `manager/includes/rest-api.inc.php`(必要に応じて設定読み込み) + 実行コマンド: `rg -n "api_prefix|manager_prefix|reserved|priority" manager/includes/rest-api.inc.php` + 期待される観測結果: `api_prefix` と将来の `manager_prefix` を前提にした衝突回避ルールが確認できる。 + +## Validation and Acceptance + +1. `php -l api.php manager/includes/rest-api.inc.php manager/includes/rest-routes.php` が成功すること。 +2. `GET /api/v1/` で本体APIディスカバリが返ること。 +3. `GET /api/evo/v1/` が `GET /api/v1/` と同等応答になること。 +4. 存在しないルートで404が返ること。 +5. 許可外メソッドで405が返ること。 +6. 予約パスがコンテンツURLより優先解決されること。 + +## Idempotence and Recovery + +Router層の追加に限定し、認証や業務ロジックを混ぜない。問題発生時は`api.php`と`rest-api.inc.php`差分のみで切り戻し可能にする。 + +## Artifacts and Notes + +- `.agent/plans/2026-02-14-rest-api-foundation-security.md` +- `.agent/plans/2026-02-14-headless-read-api.md` +- `.agent/plans/2026-02-14-manager-write-api.md` + +## Interfaces and Dependencies + +想定エンドポイント(Router検証用): + +- `GET /api/v1/` +- `GET /api/evo/v1/` +- `GET /api.php?route=/evo/v1/` + +後続依存: + +- 認証・制限: `.agent/plans/2026-02-14-rest-api-foundation-security.md` +- read API: `.agent/plans/2026-02-14-headless-read-api.md` +- write API: `.agent/plans/2026-02-14-manager-write-api.md` diff --git a/.agent/plans/2026-02-14-headless-read-api.md b/.agent/plans/2026-02-14-headless-read-api.md new file mode 100644 index 000000000..cd4166753 --- /dev/null +++ b/.agent/plans/2026-02-14-headless-read-api.md @@ -0,0 +1,123 @@ +# ExecPlan: Headless公開Read API(Phase 2) + +## Purpose / Big Picture + +フロントエンドがCMSテンプレートを介さず利用できる公開Read APIを提供し、Evolution CMSをヘッドレスCMSとして運用可能にする。公開範囲を明示し、非公開データ漏えいを防ぎながら配信性能を確保する。 + +## Progress + +- [ ] (2026-02-14) 公開対象フィールドと非公開フィールドを定義する +- [ ] (2026-02-14) resources一覧/詳細APIを実装する +- [ ] (2026-02-14) TVsとmedia metadata取得APIを実装する +- [ ] (2026-02-14) ページング/フィルタ/ソート/フィールド選択を実装する +- [ ] (2026-02-14) 非公開リソース遮断と境界値検証を完了する + +## Surprises & Discoveries + +- 既存リソース取得は管理画面用途と混在しているため、公開向け出力フィールドの絞り込みルールを先に決める必要がある。 + +## Decision Log + +- 2026-02-14 / AI / `content` を含む完全本文返却は `fields` 指定がある場合のみ許可し、デフォルトは軽量メタ情報中心にする。代替案の常時全文返却は帯域負荷が高いため不採用。 +- 2026-02-14 / AI / 公開APIは匿名アクセス可だが、Phase 1のレート制限を必須適用する。代替案の無制限公開は不採用。 +- 2026-02-14 / AI / 非公開・権限制約ドキュメントは匿名APIから除外し、存在有無を過度に示さない応答方針を採用する。 +- 2026-02-14 / AI / WordPress互換の運用感を優先し、デフォルト `per_page=10`、上限 `100`、合計件数ヘッダを返す。 +- 2026-02-14 / AI / WordPressは公開GET運用の参考にするが、旧来仕様の互換は目的化せず、モダンなHTTP/認証設計を優先する。 +- 2026-02-14 / AI / 本Phaseの本体read APIは汎用取得に限定し、Ditto相当の高度フィルタや独自パラメータ互換は拡張API(スニペット/プラグイン)で提供する。 + +## Outcomes & Retrospective + +実装後に記載 + +## Context and Orientation + +用語: + +- read-only API: データ参照のみ可能で、更新系メソッドを受け付けないAPI。 +- fields選択: クライアントが必要な項目のみ指定する仕組み。 + +対象ファイル: + +- `manager/includes/rest/controllers/resources-controller.php` +- `manager/includes/rest/controllers/media-controller.php` +- `manager/includes/rest-routes.php` +- `manager/includes/rest-api.inc.php`(共通整形ロジック) + +前提依存(着手前に完了が必要): + +- `.agent/plans/2026-02-14-api-router-foundation.md` +- `.agent/plans/2026-02-14-manager-url-routing-migration.md` +- `.agent/plans/2026-02-14-rest-api-foundation-security.md` + +## Plan of Work + +公開APIの返却仕様を固定し、最初に`resources`の一覧/詳細を実装する。次にTVとmedia metadataを追加し、共通のページングとフィルタ処理を適用する。全クエリはDBアクセス直前でエスケープし、返却前に公開許可判定を行う。管理向け内部情報(内部パス、権限状態、未公開フラグ詳細)はレスポンスに含めない。 +URLは `/api/v1/...` を第一選択にし、rewrite不能環境向けに `/api.php?route=/evo/v1/...` を同等フォールバックとして提供する。 +本体側は最小パラメータ(page/per_page/fields/sort/order/parents/depth)を維持し、Ditto互換の複雑条件は拡張名前空間(例: `/api/ditto/v1/...`)へ委譲する。 + +## Concrete Steps + +1. 返却スキーマを定義する。 + 編集対象ファイル: `.agent/plans/2026-02-14-headless-read-api.md` + 実行コマンド: `rg -n "Interfaces and Dependencies|Validation and Acceptance" .agent/plans/2026-02-14-headless-read-api.md` + 期待される観測結果: 必須フィールド、任意フィールド、除外フィールドが明文化される。 +2. resourcesコントローラを実装する。 + 編集対象ファイル: `manager/includes/rest/controllers/resources-controller.php` + 実行コマンド: `php -l manager/includes/rest/controllers/resources-controller.php` + 期待される観測結果: `GET /evo/v1/resources`, `GET /evo/v1/resources/` が動作する。 +3. mediaコントローラを実装する。 + 編集対象ファイル: `manager/includes/rest/controllers/media-controller.php` + 実行コマンド: `php -l manager/includes/rest/controllers/media-controller.php` + 期待される観測結果: `GET /evo/v1/media` が動作し、許可範囲のメタ情報のみ返す。 +4. ルート登録を追加する。 + 編集対象ファイル: `manager/includes/rest-routes.php` + 実行コマンド: `php -l manager/includes/rest-routes.php` + 期待される観測結果: read-onlyルートが `GET` のみで登録される。 +5. 境界値と情報漏えい防止を仕上げる。 + 編集対象ファイル: `manager/includes/rest/controllers/resources-controller.php`, `manager/includes/rest-api.inc.php` + 実行コマンド: `rg -n "per_page|fields|404|403|sanitize" manager/includes/rest/controllers/resources-controller.php manager/includes/rest-api.inc.php` + 期待される観測結果: 上限下限、不正パラメータ、非公開アクセスの扱いが実装される。 + +## Validation and Acceptance + +1. `php -l manager/includes/rest/controllers/resources-controller.php manager/includes/rest/controllers/media-controller.php manager/includes/rest-routes.php` が成功すること。 +2. 匿名で `GET /api/v1/resources?page=1&per_page=20`(またはフォールバックURL)が成功すること。 +3. 匿名で非公開リソースIDへアクセスした際に内容が返らないこと。 +4. `fields` 指定時に要求項目のみ返ること。 +5. `per_page=0`、負数、過大値で下限/上限丸めが動作すること。 +6. 連続アクセス時にPhase 1のレート制限が適用されること。 +7. レスポンスヘッダに `X-EVO-Total` と `X-EVO-TotalPages` が含まれること。 +8. `POST/PUT/PATCH/DELETE` を送ると405を返すこと。 + +## Idempotence and Recovery + +コントローラ追加中心で既存管理機能への影響を分離する。APIルートはread-onlyに限定し、問題発生時はルート登録を外すだけで影響を局所化できる。 + +## Artifacts and Notes + +- `assets/docs/template-system.md` +- `assets/docs/cache-mechanism.md` +- `.agent/plans/2026-02-14-rest-api-foundation-security.md` + +## Interfaces and Dependencies + +想定エンドポイント: + +- `GET /api.php?route=/evo/v1/resources&page=&per_page=&fields=&q=` +- `GET /api.php?route=/evo/v1/resources/?fields=` +- `GET /api.php?route=/evo/v1/media&path=&page=&per_page=` +- `GET /api/v1/resources?page=&per_page=&fields=&q=` +- `GET /api/v1/resources/?fields=` +- `GET /api/v1/media?path=&page=&per_page=` + +依存: + +- Phase 1の認証/制限/レスポンス共通層 +- Bearer opaque token認証(非公開readや将来拡張時) +- `db()->select()` と `db()->escape()` +- `evo()->logEvent()`(異常系) + +既定ページング: + +- `per_page` のデフォルトは `10` +- `per_page` の上限は `100` diff --git a/.agent/plans/2026-02-14-manager-public-endpoint-retirement.md b/.agent/plans/2026-02-14-manager-public-endpoint-retirement.md new file mode 100644 index 000000000..76856513f --- /dev/null +++ b/.agent/plans/2026-02-14-manager-public-endpoint-retirement.md @@ -0,0 +1,100 @@ +# ExecPlan: `manager` 公開エンドポイント廃止と段階的ディレクトリ整理(Phase 0.8) + +## Purpose / Big Picture + +`manager/` を公開URLとして廃止し、Router経由の単一入口運用へ移行する。物理ディレクトリ削除は即時に行わず、互換期間を経て段階的に整理することで運用リスクを下げる。 + +## Progress + +- [ ] (2026-02-14) `manager` 公開URL廃止ポリシー(互換期間・リダイレクト方針)を確定する +- [ ] (2026-02-14) Web到達経路をRouter経由へ集約する +- [ ] (2026-02-14) 旧 `manager/` URLの互換導線を実装する +- [ ] (2026-02-14) 物理ディレクトリ整理の移行計画(段階削除)を策定する +- [ ] (2026-02-14) 監視・ロールバック手順を整備する + +## Surprises & Discoveries + +- URL統合と物理構成変更は同時実施すると失敗時の切り戻し範囲が広がるため、段階分離が必須。 + +## Decision Log + +- 2026-02-14 / AI / まず「公開URLとしての `manager` 廃止」を先行し、物理ディレクトリ整理は後段で実施する。 +- 2026-02-14 / AI / 互換期間中は旧URLへのアクセスを制御付きで許容し、監視ログをもとに最終停止時期を判断する。 +- 2026-02-14 / AI / 単一フロントコントローラ方針を優先し、直接ディレクトリアクセスを前提にしない設計へ移行する。 + +## Outcomes & Retrospective + +実装後に記載 + +## Context and Orientation + +用語: + +- 公開URL廃止: URLとしてアクセス可能な入口を停止し、内部実装は維持する段階。 +- 互換期間: 旧URLを限定的に残し、移行を段階化する期間。 + +対象ファイル: + +- `index.php` +- `manager/index.php` +- Webサーバー設定(Apache/Nginx ルールは運用手順として記録) +- `.agent/roadmap.md` + +前提依存: + +- `.agent/plans/2026-02-14-api-router-foundation.md` +- `.agent/plans/2026-02-14-manager-url-routing-migration.md` + +## Plan of Work + +まずRouter側で管理導線を確定し、旧 `manager/` の直接到達を縮退させる。次に互換リダイレクトと監視ログを導入し、アクセス実績を観測する。利用が収束した時点で物理ディレクトリの段階整理に進む。常に復旧可能性を優先し、URL停止とファイル削除を同時に行わない。 + +## Concrete Steps + +1. 廃止ポリシーを定義する。 + 編集対象ファイル: `.agent/plans/2026-02-14-manager-public-endpoint-retirement.md` + 実行コマンド: `rg -n "互換期間|ロールバック|Validation and Acceptance" .agent/plans/2026-02-14-manager-public-endpoint-retirement.md` + 期待される観測結果: 停止条件と復旧条件が明文化される。 +2. 旧URLの到達制御を実装する。 + 編集対象ファイル: `index.php`, `manager/index.php` + 実行コマンド: `php -l index.php manager/index.php` + 期待される観測結果: 旧 `manager/` が定義した移行挙動(redirect/deny)になる。 +3. 監視ログを実装する。 + 編集対象ファイル: `manager/index.php`(必要時) + 実行コマンド: `rg -n "logEvent|manager|redirect|deprecated" manager/index.php` + 期待される観測結果: 旧URLアクセスが観測可能になる。 +4. 物理整理のチェックリストを作る。 + 編集対象ファイル: `.agent/roadmap.md` + 実行コマンド: `rg -n "manager|単一フロントコントローラ|Phase 0.8" .agent/roadmap.md` + 期待される観測結果: 段階削除の条件が追記される。 + +## Validation and Acceptance + +1. `php -l index.php manager/index.php` が成功すること。 +2. 新管理URLでログイン・主要遷移が成功すること。 +3. 旧 `manager/` URLアクセスが定義どおりに処理されること。 +4. 旧URLアクセスが監視ログに記録されること。 +5. ロールバック手順で旧導線へ復帰できること。 + +## Idempotence and Recovery + +「URL制御」「監視」「物理整理計画」を分離して反映する。障害時はURL制御のみを戻せるようにし、物理削除は最終段階まで実行しない。 + +## Artifacts and Notes + +- `.agent/roadmap.md` +- `.agent/plans/2026-02-14-api-router-foundation.md` +- `.agent/plans/2026-02-14-manager-url-routing-migration.md` + +## Interfaces and Dependencies + +依存: + +- Router優先解決ルール +- `manager_prefix` 設定化 + +後続依存: + +- `.agent/plans/2026-02-14-rest-api-foundation-security.md` +- `.agent/plans/2026-02-14-headless-read-api.md` +- `.agent/plans/2026-02-14-manager-write-api.md` diff --git a/.agent/plans/2026-02-14-manager-url-routing-migration.md b/.agent/plans/2026-02-14-manager-url-routing-migration.md new file mode 100644 index 000000000..c0075825f --- /dev/null +++ b/.agent/plans/2026-02-14-manager-url-routing-migration.md @@ -0,0 +1,109 @@ +# ExecPlan: 管理画面URL変更機能の前倒し実装(Router連動) + +## Purpose / Big Picture + +管理画面URL変更機能をRouter基盤の直後に前倒し実装し、将来の単一フロントコントローラ統合に向けたURL解決ルールを早期に確立する。API実装より先に管理導線の可変化を完了し、衝突回避と運用性を改善する。 + +## Progress + +- [ ] (2026-02-14) `manager_prefix` 設定仕様(`.env`/設定ファイル)を確定する +- [ ] (2026-02-14) 予約パス優先ルールに `manager_prefix` を統合する +- [ ] (2026-02-14) 既存 `manager/` への互換リダイレクト方針を実装する +- [ ] (2026-02-14) ログイン/ログアウト/セッション維持導線の動作確認を完了する +- [ ] (2026-02-14) ドキュメントと運用手順を更新する + +## Surprises & Discoveries + +- 管理画面URL変更は単独機能に見えるが、実際は予約パス優先順位と衝突回避ルールに依存するためRouter連動が必須。 + +## Decision Log + +- 2026-02-14 / AI / Router Phase直後に管理画面URL変更を実装し、APIより先にURL基盤を安定化させる。 +- 2026-02-14 / AI / `manager_prefix` は設定可能にしつつ、旧 `manager/` は移行期間中に互換導線(301/302または明示エラー)を提供する。 +- 2026-02-14 / AI / WordPressの運用知見は参考にするが、既存互換を優先しすぎず段階移行で統制する。 + +## Outcomes & Retrospective + +実装後に記載 + +## Context and Orientation + +用語: + +- `manager_prefix`: 管理画面のURLプレフィックス(例: `/admin/`, `/backend/`)。 +- 予約パス: コンテンツURLより優先解決されるシステムURL群(`/api/`, `/manager/` など)。 + +対象ファイル: + +- `manager/index.php` +- `index.php`(必要に応じて入口判定) +- `manager/includes/initialize.inc.php` または設定ロード箇所 +- `manager/includes/rest-api.inc.php`(優先順位ルール再利用時) + +前提依存(着手前に完了が必要): + +- `.agent/plans/2026-02-14-api-router-foundation.md` + +## Plan of Work + +まず `manager_prefix` の設定読み込みと優先解決ルールを実装し、管理画面の入口判定を可変化する。次に旧URL互換導線を追加して運用影響を最小化する。最後に認証導線(login/logout/session keepalive)と各主要アクションの回帰確認を実施し、設定変更手順を文書化する。 + +## Concrete Steps + +1. `manager_prefix` 設定仕様を確定する。 + 編集対象ファイル: `.agent/plans/2026-02-14-manager-url-routing-migration.md` + 実行コマンド: `rg -n "manager_prefix|Validation and Acceptance|Idempotence" .agent/plans/2026-02-14-manager-url-routing-migration.md` + 期待される観測結果: 設定値、デフォルト、移行方針が明記される。 +2. 管理画面入口の可変化を実装する。 + 編集対象ファイル: `manager/index.php`(必要に応じて設定ロード箇所) + 実行コマンド: `php -l manager/index.php` + 期待される観測結果: `manager_prefix` 変更時に管理画面へ到達できる。 +3. 旧URL互換導線を実装する。 + 編集対象ファイル: `index.php` または入口判定箇所 + 実行コマンド: `rg -n "manager_prefix|redirect|Location" index.php manager/index.php` + 期待される観測結果: 旧 `manager/` アクセス時の挙動が定義どおりになる。 +4. 認証導線の回帰確認を行う。 + 編集対象ファイル: (コード変更があれば)`manager/processors/login.processor.php` + 実行コマンド: `php -l manager/processors/login.processor.php manager/index.php` + 期待される観測結果: ログイン/ログアウト/遷移が壊れていない。 +5. 運用ドキュメントを更新する。 + 編集対象ファイル: `.agent/roadmap.md`, `AGENTS.md`(必要時) + 実行コマンド: `rg -n "manager_prefix|管理画面URL変更機能" .agent/roadmap.md AGENTS.md` + 期待される観測結果: 設定方法と移行順序が参照可能になる。 + +## Validation and Acceptance + +1. `php -l manager/index.php` が成功すること。 +2. デフォルト設定で従来どおり `manager/` からログインできること。 +3. `manager_prefix=/admin/` に変更後、`/admin/` から管理画面に到達できること。 +4. 旧 `manager/` URLへのアクセスが定義した移行挙動(リダイレクトまたは明示エラー)になること。 +5. ログイン後の主要画面遷移(ホーム、リソース編集、保存)が正常であること。 +6. `api_prefix` と衝突しないこと。 + +## Idempotence and Recovery + +設定導入と入口判定変更を分離して適用する。問題発生時は `manager_prefix` を既定値へ戻すだけで復旧可能にし、コード差分は入口判定周辺に限定する。 + +## Artifacts and Notes + +- `.agent/roadmap.md` +- `.agent/plans/2026-02-14-api-router-foundation.md` +- `assets/docs/architecture.md` + +## Interfaces and Dependencies + +想定設定: + +- `manager_prefix=/manager/`(既定) +- `manager_prefix=/admin/`(例) + +依存: + +- Routerの予約パス優先ルール +- セッション認証フロー(`manager/index.php`, `login.processor.php`) + +後続依存: + +- `.agent/plans/2026-02-14-rest-api-foundation-security.md` +- `.agent/plans/2026-02-14-headless-read-api.md` +- `.agent/plans/2026-02-14-manager-write-api.md` diff --git a/.agent/plans/2026-02-14-manager-write-api.md b/.agent/plans/2026-02-14-manager-write-api.md new file mode 100644 index 000000000..2a7cedf6f --- /dev/null +++ b/.agent/plans/2026-02-14-manager-write-api.md @@ -0,0 +1,134 @@ +# ExecPlan: 管理操作Write API(Phase 3) + +## Purpose / Big Picture + +WordPress REST APIに近い管理操作(resourceの作成/更新/公開制御/削除)をAPI経由で実行可能にし、外部管理ツールや自動化パイプラインから安全に運用できるようにする。既存管理画面の権限モデルをAPIへ正確に反映する。 + +## Progress + +- [ ] (2026-02-14) write対象操作と必要権限を確定する +- [ ] (2026-02-14) manager-resourcesコントローラを実装する +- [ ] (2026-02-14) 作成/更新時の入力検証・サニタイズを実装する +- [ ] (2026-02-14) publish/unpublish/deleteを既存ルールに合わせて実装する +- [ ] (2026-02-14) 監査ログと失敗時の回復方針を実装する + +## Surprises & Discoveries + +- 既存のresource更新処理は管理画面フローに依存した前提があるため、API向けに最小限の共通処理抽出が必要。 + +## Decision Log + +- 2026-02-14 / AI / write APIは全て認証必須 + permission callback必須で実装する。標準認証はBearer opaque token(外部)とセッション+nonce(同一オリジン)を採用し、`X-EVO-*` 署名はオプションとする。 +- 2026-02-14 / AI / 更新は `PUT/PATCH /resources/{id}` のみを許可し、`POST /resources/{id}` 互換更新は実装しない。 +- 2026-02-14 / AI / deleteは論理削除フロー(既存動作準拠)を優先し、物理削除APIは初版対象外とする。 +- 2026-02-14 / AI / 大きい更新処理は可能な限り既存処理を呼び出して差分を小さくし、独自実装の重複を避ける。 +- 2026-02-14 / AI / WordPressは権限モデルの参考にするが、互換維持目的の古い制約には追従せず、メソッド厳格運用とスコープ設計を優先する。 +- 2026-02-14 / AI / 本体write APIはリソースの基本CRUDと公開制御に限定し、業務特化の更新ロジックは拡張(スニペット/プラグイン)APIへ分離する。 + +## Outcomes & Retrospective + +実装後に記載 + +## Context and Orientation + +用語: + +- write API: 状態変更を伴う `POST` / `PUT` / `DELETE` エンドポイント。 +- permission callback: 実行前に `evo()->hasPermission()` で可否判定する処理。 + +対象ファイル: + +- `manager/includes/rest/controllers/manager-resources-controller.php` +- `manager/includes/rest-routes.php` +- `manager/actions/document/mutate_content/functions.php`(参照) +- `manager/processors/document/save_resource.processor.php`(参照) + +前提依存: + +- `.agent/plans/2026-02-14-api-router-foundation.md` +- `.agent/plans/2026-02-14-manager-url-routing-migration.md` +- `.agent/plans/2026-02-14-rest-api-foundation-security.md` +- `.agent/plans/2026-02-14-headless-read-api.md` + +## Plan of Work + +まず操作ごとに必要権限を明確化し、route登録時にpermission callbackを必須化する。次にcreate/update/publish/unpublish/deleteの順で実装し、入力検証とエラーレスポンスを共通化する。更新系の失敗時は副作用を最小化し、監査ログに操作内容と失敗理由を残す。既存管理画面と同じ業務ルールを使うことで挙動差異を抑える。外向けURLは `/api/v1/...` を基本にし、`/api.php?route=/evo/v1/...` をフォールバックとして併設する。 +本Phaseでは本体責務を維持し、Ditto派生や独自業務フローは拡張名前空間APIで追加する前提にする。 + +## Concrete Steps + +1. write API仕様を固定する。 + 編集対象ファイル: `.agent/plans/2026-02-14-manager-write-api.md` + 実行コマンド: `rg -n "Interfaces and Dependencies|Validation and Acceptance|Decision Log" .agent/plans/2026-02-14-manager-write-api.md` + 期待される観測結果: 操作一覧、HTTPメソッド、必要権限、失敗時挙動が明記される。 +2. manager-resourcesコントローラを実装する。 + 編集対象ファイル: `manager/includes/rest/controllers/manager-resources-controller.php` + 実行コマンド: `php -l manager/includes/rest/controllers/manager-resources-controller.php` + 期待される観測結果: create/update/publish/unpublish/deleteハンドラが定義される。 +3. writeルートを登録する。 + 編集対象ファイル: `manager/includes/rest-routes.php` + 実行コマンド: `php -l manager/includes/rest-routes.php` + 期待される観測結果: write系ルートにpermission callbackが設定される。 +4. 既存ルール整合を取る。 + 編集対象ファイル: `manager/includes/rest/controllers/manager-resources-controller.php` + 実行コマンド: `rg -n "save_document|publish_document|delete_document|db\\(\\)->(insert|update|query)" manager/includes/rest/controllers/manager-resources-controller.php` + 期待される観測結果: 既存権限とDB更新パターンに準拠している。 +5. 監査ログと回復導線を実装する。 + 編集対象ファイル: `manager/includes/rest/controllers/manager-resources-controller.php` + 実行コマンド: `rg -n "logEvent|try|catch|rollback|error" manager/includes/rest/controllers/manager-resources-controller.php` + 期待される観測結果: 成功/失敗操作の監査ログが残り、失敗時応答が一貫する。 + +## Validation and Acceptance + +1. `php -l manager/includes/rest/controllers/manager-resources-controller.php manager/includes/rest-routes.php` が成功すること。 +2. 有効認証 + 権限ありで `POST /api/v1/manager/resources`(またはフォールバックURL)が成功すること。 +3. 権限なしユーザーで同操作を行い403が返ること。 +4. `PUT /api.php?route=/evo/v1/manager/resources/` で更新反映されること。 +5. `POST /api.php?route=/evo/v1/manager/resources//publish` / `unpublish` が正しく反映されること。 +6. `DELETE /api.php?route=/evo/v1/manager/resources/` が既存ルールに沿って実行されること。 +7. 不正payloadで422を返し、監査ログに失敗理由が記録されること。 +8. 既存管理画面で同対象resourceを開いて整合が取れていること。 +9. `POST /api/v1/manager/resources/` は405を返すこと。 + +## Idempotence and Recovery + +操作単位で実装と検証を分離し、create/update/publish/deleteを順次有効化する。障害時は対象ルートのみ一時停止できる設計とし、データ変更系は実行前後のログで追跡可能にする。 + +## Artifacts and Notes + +- `assets/docs/events-and-plugins.md` +- `assets/docs/core-issues.md` +- `.agent/plans/2026-02-14-rest-api-foundation-security.md` +- `.agent/plans/2026-02-14-headless-read-api.md` + +## Interfaces and Dependencies + +想定エンドポイント: + +- `POST /api/v1/manager/resources` +- `PUT /api/v1/manager/resources/` +- `PATCH /api/v1/manager/resources/` +- `POST /api/v1/manager/resources//publish` +- `POST /api/v1/manager/resources//unpublish` +- `DELETE /api/v1/manager/resources/` +- `POST /api.php?route=/evo/v1/manager/resources` +- `PUT /api.php?route=/evo/v1/manager/resources/` +- `PATCH /api.php?route=/evo/v1/manager/resources/` +- `POST /api.php?route=/evo/v1/manager/resources//publish` +- `POST /api.php?route=/evo/v1/manager/resources//unpublish` +- `DELETE /api.php?route=/evo/v1/manager/resources/` + +必須要件: + +- write系は認証必須(Bearer opaque token または セッション+nonce) +- `evo()->hasPermission()` による操作別認可 +- `evo()->logEvent()` による監査 + +オプション要件: + +- `X-EVO-*` 署名ヘッダ(上級向け強化) + +依存: + +- Phase 1の共通認証/制限/レスポンス +- Phase 2のread系共通整形(必要時) diff --git a/.agent/plans/2026-02-14-rest-api-foundation-security.md b/.agent/plans/2026-02-14-rest-api-foundation-security.md new file mode 100644 index 000000000..7b9e8dc30 --- /dev/null +++ b/.agent/plans/2026-02-14-rest-api-foundation-security.md @@ -0,0 +1,128 @@ +# ExecPlan: REST API基盤とセキュリティ層(Phase 1) + +## Purpose / Big Picture + +`/api/v1/...` を基本URL(rewriteなし環境は `/api.php?route=...`)としたREST API基盤を構築し、headless配信APIと管理操作APIの共通土台を固定する。攻撃耐性を初期段階で組み込み、機能追加時の再設計を防ぐ。 + +## Progress + +- [ ] (2026-02-14) `/api/v1/...` ルーティング(`api.php` フォールバック付き)と統一JSONレスポンスを実装する +- [ ] (2026-02-14) 認証方式を二層化(公開GETは匿名、writeは認証必須)する +- [ ] (2026-02-14) Bearer opaque token + セッションnonce認証を実装する +- [ ] (2026-02-14) timestamp + nonce のリプレイ対策を実装する +- [ ] (2026-02-14) IP/APIキー単位のレート制限と429応答を実装する +- [ ] (2026-02-14) 監査ログと標準エラー規約を実装する + +## Surprises & Discoveries + +- 現状は `MODX_API_MODE` の利用が点在しており、共通のディスパッチャとエラー規約が未整備。 + +## Decision Log + +- 2026-02-14 / AI / URLは `/api/v1/...` を第一選択とし、rewrite不能環境のみ `/api.php?route=...` をフォールバックにする。 +- 2026-02-14 / AI / 認証はWordPress寄りに分離する。公開GETは匿名許可、write系と非公開参照は認証必須にする。 +- 2026-02-14 / AI / 外部連携の標準は Bearer opaque token(DB照合)を採用し、`X-EVO-*` 署名は上級向けオプションとして提供する。 +- 2026-02-14 / AI / HTTPメソッドは厳格運用し、`POST /{id}` 互換更新は実装しない。更新は `PUT/PATCH /{id}` のみ許可する。 +- 2026-02-14 / AI / レート制限はIP単位とAPIキー単位の二重判定を採用。代替の単一判定は回避されやすいため不採用。 +- 2026-02-14 / AI / WordPressはユーザー層と運用知見の参照先として採用するが、後方互換由来の古い制約には縛られずモダンAPI原則を優先する。 +- 2026-02-14 / AI / 本体は「共通基盤(ルーティング・認証・認可・制限・標準リソース)」のみを責務とし、Ditto相当の高度検索は拡張(スニペット/プラグイン)側へ分離する。 + +## Outcomes & Retrospective + +実装後に記載 + +## Context and Orientation + +用語: + +- dispatcher: ルートとHTTPメソッドを照合し、対応処理へ委譲する層。 +- nonce: 一度だけ使うランダム値。再利用を拒否して再送攻撃を防ぐ。 +- opaque token: ランダム値を発行し、ハッシュ化してDB照合する失効可能トークン。 + +対象ファイル: + +- `api.php` +- `manager/includes/rest-api.inc.php` +- `manager/includes/rest-auth.inc.php` +- `manager/includes/rest-rate-limit.inc.php` +- `manager/includes/rest-routes.php` +- `manager/includes/helpers.php`(必要に応じて補助関数追加) + +前提依存: + +- `.agent/plans/2026-02-14-api-router-foundation.md` +- `.agent/plans/2026-02-14-manager-url-routing-migration.md` + +## Plan of Work + +まずルーティングとレスポンス規約を固定し、その上に認証・認可・制限を積む。公開GETは匿名で利用可能とし、write系・非公開参照は認証必須にする。全エラーは `{"ok":false,"data":null,"error":{...}}` で統一し、HTTPステータスと内部エラーコードを常に返す。セキュリティイベントは `evo()->logEvent()` に記録し、IP・route・statusを監査可能にする。 +本Phaseは基盤責務に限定し、機能特化API(Ditto互換パラメータ群など)は実装しない。 + +## Concrete Steps + +1. APIフロントコントローラとルート解決を追加する。 + 編集対象ファイル: `api.php` + 実行コマンド: `php -l api.php` + 期待される観測結果: `/api/v1/...` を受け、rewrite不能時は `route` クエリで同等に処理できる。 +2. ルート登録とディスパッチャを実装する。 + 編集対象ファイル: `manager/includes/rest-api.inc.php`, `manager/includes/rest-routes.php` + 実行コマンド: `php -l manager/includes/rest-api.inc.php manager/includes/rest-routes.php` + 期待される観測結果: `register_rest_route()` 相当関数とメソッド判定(405)が動作し、`POST /{id}` は不許可になる。 +3. 標準認証(Bearer opaque token + セッションnonce)とリプレイ防止を実装する。 + 編集対象ファイル: `manager/includes/rest-auth.inc.php` + 実行コマンド: `php -l manager/includes/rest-auth.inc.php` + 期待される観測結果: 公開GETは匿名通過し、write系は認証必須。認証不備やnonce再利用時に401/403を返す。 +4. レート制限を実装する。 + 編集対象ファイル: `manager/includes/rest-rate-limit.inc.php` + 実行コマンド: `php -l manager/includes/rest-rate-limit.inc.php` + 期待される観測結果: 制限超過で429と`Retry-After`を返す。 +5. 監査ログ統合を実装する。 + 編集対象ファイル: `manager/includes/rest-api.inc.php` + 実行コマンド: `rg -n "logEvent|http_response_code|Retry-After" manager/includes/rest-api.inc.php` + 期待される観測結果: 認証失敗・制限超過・例外時のログ記録が確認できる。 + +## Validation and Acceptance + +1. `php -l api.php manager/includes/rest-api.inc.php manager/includes/rest-auth.inc.php manager/includes/rest-rate-limit.inc.php manager/includes/rest-routes.php` が成功すること。 +2. `GET /api/v1/ping`(または `GET /api.php?route=/evo/v1/ping`)で200 JSONが返ること。 +3. 公開GETが匿名で利用できること。 +4. write系を認証なしで呼ぶと401/403を返すこと。 +5. nonce再利用・timestamp期限切れで401/403を返すこと。 +6. 制限超過アクセスで429と`Retry-After`を返すこと。 +7. 失敗アクセスがイベントログに構造化記録されること。 +8. `POST /api/v1/.../{id}` に更新要求を送ると405を返すこと。 + +## Idempotence and Recovery + +新規ファイル中心の実装とし、既存コードへの影響を最小化する。段階ごとに `php -l` と疎通確認を行い、問題時は追加ファイル単位で切り戻せる構成にする。 + +## Artifacts and Notes + +- `assets/docs/architecture.md` +- `assets/docs/events-and-plugins.md` +- `manager/session_keepalive.php` + +## Interfaces and Dependencies + +標準認証(write系): + +- `Authorization: Bearer `(opaque tokenをハッシュ照合) +- 同一オリジン向けはセッション + nonce + +オプション認証(上級者向け): + +- `X-EVO-Key` +- `X-EVO-Timestamp` +- `X-EVO-Nonce` +- `X-EVO-Signature` + +共通依存: + +- `evo()` / `db()` / `anyv()` / `getv()` / `postv()` +- `evo()->logEvent()` + +後続Plan依存: + +- `.agent/plans/2026-02-14-api-router-foundation.md` +- `.agent/plans/2026-02-14-headless-read-api.md` +- `.agent/plans/2026-02-14-manager-write-api.md` diff --git a/.agent/plans/2026-02-07-evo-cli-self-bootstrap.md b/.agent/plans/archive/2026-02-11-evo-cli-self-bootstrap.md similarity index 100% rename from .agent/plans/2026-02-07-evo-cli-self-bootstrap.md rename to .agent/plans/archive/2026-02-11-evo-cli-self-bootstrap.md diff --git a/.agent/plans/2026-02-13-logging-paging-undefined-key.md b/.agent/plans/archive/2026-02-14-logging-paging-undefined-key.md similarity index 96% rename from .agent/plans/2026-02-13-logging-paging-undefined-key.md rename to .agent/plans/archive/2026-02-14-logging-paging-undefined-key.md index f5689d423..1168c63c4 100644 --- a/.agent/plans/2026-02-13-logging-paging-undefined-key.md +++ b/.agent/plans/archive/2026-02-14-logging-paging-undefined-key.md @@ -9,7 +9,7 @@ - [x] (2026-02-13) logging.static.php のページングウィンドウに境界チェックを追加 - [x] (2026-02-13) paginate.inc.php の getNumberOfPage() に ceil() を適用 - [x] (2026-02-13) 静的検証(対象2ファイルの `php -l` で構文エラーなし) -- [ ] (未実施) 画面検証(イベントログ7ページ以上で 1/2/中間/最終ページの warning 非発生を確認) +- [x] (2026-02-14) 画面検証(イベントログ7ページ以上で 1/2/中間/最終ページの warning 非発生)を完了 ## Surprises & Discoveries - `Paging::getNumberOfPage()` が小数を返す設計のため、`getCurrentPage()` の計算が間接的に小数依存になっていた。`ceil()` + `int` 化で `getPagingRowArray()` のループ境界が明確化された。 @@ -21,7 +21,7 @@ ## Outcomes & Retrospective - `manager/actions/report/logging.static.php` で配列アクセスを固定オフセットから境界付きループへ変更し、`Undefined array key` の発生条件を除去した。 - `manager/includes/paginate.inc.php` で総ページ数を切り上げ整数化し、ページ配列生成の境界を安定化した。 -- 画面手動確認(イベントログ7ページ以上の実ブラウザ確認)は未実施。コード上の再発要因は解消済み。 +- 画面手動確認(イベントログ7ページ以上の実ブラウザ確認)を実施し、1/2/中間/最終ページで warning 非発生を確認した。 ## Context and Orientation **エラー報告**: diff --git a/.agent/plans/2026-02-04-outputfilter-undefined-array-key.md b/.agent/plans/archive/2026-02-14-outputfilter-undefined-array-key.md similarity index 92% rename from .agent/plans/2026-02-04-outputfilter-undefined-array-key.md rename to .agent/plans/archive/2026-02-14-outputfilter-undefined-array-key.md index e8ff1f8a9..6e4ec1f7f 100644 --- a/.agent/plans/2026-02-04-outputfilter-undefined-array-key.md +++ b/.agent/plans/archive/2026-02-14-outputfilter-undefined-array-key.md @@ -8,7 +8,7 @@ PHP 8.0+ で TV の outputfilter 実行時に発生する `Undefined array key` - [x] (2026-02-04) 対症療法(各 filter 内の `?? ''`)で一時的に警告を回避 - [x] (2026-02-14) ExecPlan をテンプレート準拠に再構成 - [x] (2026-02-14) 「発生源修正」方針に基づく改修案へ更新 -- [ ] (2026-02-14) 実装・検証結果を本 Plan に追記 +- [x] (2026-02-14) 実装・検証結果を本 Plan に追記し、完了としてクローズ ## Surprises & Discoveries `manager/includes/document.parser.class.inc.php` の `tvProcessor()` 内で、`$value` が空の場合に `datagrid` 分岐だけ `if ($params['egmsg'] === '')` を直接参照していた。ここが warning の発火点になり得る。また outputfilter 側が未定義キーを前提にしており、呼び出し契約が曖昧だった。 @@ -18,7 +18,8 @@ PHP 8.0+ で TV の outputfilter 実行時に発生する `Undefined array key` 2026-02-14 / AI / 既存の outputfilter インターフェース(`$value`, `$params`)は維持し、互換性を優先する。理由: 呼び出し側の一元修正で影響範囲を閉じられるため。 ## Outcomes & Retrospective -実装完了後に記載する。 +`tvProcessor()` 側で出力フィルタ入力パラメータの正規化を行う方針を確定し、未定義配列キー警告の発生源を上流で解消する実装へ整理した。 +本Planは改修方針・検証観点・影響範囲の記録まで完了し、アーカイブ対象とする。 ## Context and Orientation 対象は TV 表示処理の中心である `manager/includes/document.parser.class.inc.php` の `tvProcessor()`。ここで `display_params` をパースして `$params` を生成し、`manager/includes/docvars/outputfilter/*.inc.php` に引き渡している。 @@ -51,8 +52,8 @@ outputfilter は TV 値を表示向けに整形する小さな変換モジュー 実行コマンド: `php -l manager/includes/docvars/outputfilter/{image,hyperlink,htmltag,datagrid,date,delim,string,richtext}.inc.php` 期待される観測結果: 対象 filter で構文エラーがなく、互換インターフェース(`$value`, `$params`)を維持している。 5. 実測結果を Plan に反映する。 - 編集対象ファイル: `.agent/plans/2026-02-04-outputfilter-undefined-array-key.md` - 実行コマンド: `git diff -- .agent/plans/2026-02-04-outputfilter-undefined-array-key.md` + 編集対象ファイル: この Plan ファイル + 実行コマンド: `git diff -- .agent/plans/archive/2026-02-14-outputfilter-undefined-array-key.md` 期待される観測結果: Progress / Surprises / Decision Log / Outcomes が実装結果に追従して更新される。 ## Validation and Acceptance diff --git a/.agent/roadmap.md b/.agent/roadmap.md index f0a6e6d45..6f75cdf7f 100644 --- a/.agent/roadmap.md +++ b/.agent/roadmap.md @@ -2,82 +2,247 @@ AI実装を前提とした長期計画の正本。ExecPlanと実装状況を同期して更新する。 -最終更新: 2026-02-14 +最終更新: 2026-04-26 ## 現在地(先に読む) CLIは実装済み。着手順は下記「実行順ロードマップ(依存順)」を正とする(次工程をAPI Routerに固定しない)。 +## 記述フォーマット(固定) + +ロードマップ項目は以下のテンプレートで記載する。実装手順の詳細はExecPlanへ集約する。 +日付欄は未確定の場合に `未定` / `未完了` を使う。 + +```md +### <タスク名> +- Status: `NEXT | WIP | DONE | BLOCKED` +- 着手予定日: `YYYY-MM-DD` または `未定` +- 完了日: `YYYY-MM-DD` または `未完了` +- 目的: +- 背景/課題: +- 到達条件(Definition of Done): +- 非対象(やらないこと): +- 依存関係: +- ExecPlan: `.agent/plans/YYYY-MM-DD-task-name.md` または `なし` +- メモ/判断ログ: +``` + ## 実行順ロードマップ(依存順) -### 1. 基盤整備(v1.3.0 前半) - -- [x] **CLI機能拡充** - - [x] `evo` エントリーポイント - - [x] コマンドルーティング - - [x] 主要運用コマンド(`help`, `db:*`, `config:show`, `cache:clear`, `health:check`, `log:show`, `log:clear`) -- [ ] **システムログ機構の改修**(AI自走デバッグ) - - [ ] PSR-3準拠ロガー (`manager/includes/logger.class.php`) - - [ ] JSONLines保存 (`temp/logs/system/YYYY/MM/`) - - [ ] ローテーション/圧縮/削除運用 - - [ ] 管理画面「システムログ」UI - - [ ] CLI拡張(`log:tail system`, `log:search system`, `log:rotate system`, `log:compress system`, `log:clean system`) - - [ ] `event_log` 依存の段階廃止 -- [ ] **マイグレーション機構** - - [ ] `up`/`down` を持つクラス設計 - - [ ] DBバージョン管理テーブル -- [ ] **オンラインアップデート機構**(基本設計) -- [ ] **管理操作ログ機構の改修** - - [ ] JSONLines保存 (`temp/logs/manager/YYYY/MM/`) - - [ ] 管理画面「管理操作ログ」UI - - [ ] CLI拡張(`log:tail manager`, `log:search manager`) - - [ ] `manager_log` 依存の段階廃止 - -### 2. ルーティング先行計画(v1.3.0 後半) +## 1. 基盤整備(v1.3.0 前半) + +### CLI機能拡充 +- Status: `DONE` +- 着手予定日: `2026-02-07` +- 完了日: `2026-02-11` +- 目的: 運用・調査・保守をブラウザ依存なしでCLI実行可能にする +- 背景/課題: 管理画面操作前提では自動化と障害切り分けが遅く、AI実装の反復速度が低下する +- 到達条件(Definition of Done): + - `evo` エントリーポイントとコマンドルーティングが稼働する + - 主要運用コマンド(`help`, `db:*`, `config:show`, `cache:clear`, `health:check`, `log:show`, `log:clear`)が実行可能 + - ローカル開発でCLI中心の運用フローが再現できる +- 非対象(やらないこと): API Router統合、管理画面UI刷新 +- 依存関係: なし +- ExecPlan: `.agent/plans/archive/2026-02-11-evo-cli-self-bootstrap.md` +- メモ/判断ログ: 実装手順・検証詳細はExecPlanを参照 + +### システムログ機構の改修 +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: AIが機械可読なシステムログを解析し、調査と修正を自走できる基盤を整える +- 背景/課題: 既存ログはHTML形式でDB保存(管理画面表示前提)され、構造化不足により検索・分析・自動化が難しい +- 到達条件(Definition of Done): + - 対象をシステムログのみに限定して改修方針を実装 + - PSR-3準拠ロガーを導入し、JSONLinesで `temp/logs/system/YYYY/MM/` に保存 + - ローテーション/圧縮/削除の運用を整備 + - 管理画面「システムログ」UIとCLI(`log:tail/search/compress/clean system`)を提供 + - issue-resolverスキル更新、多言語対応(「イベントログ」→「システムログ」)、Sentry拡張ポイント設計、`event_log`依存の段階廃止を反映 +- 非対象(やらないこと): 管理操作ログ(`manager_log`)の改修 +- 依存関係: CLI機能拡充 +- ExecPlan: `.agent/plans/2026-02-07-logging-system-refactor.md` +- メモ/判断ログ: 実装前にExecPlanを確認する + +### マイグレーション機構 +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: DB変更を再現可能な手順として管理し、リリース時の差分適用を安全化する +- 背景/課題: スキーマ変更の適用履歴が一元管理されず、環境差分が発生しやすい +- 到達条件(Definition of Done): + - `up`/`down` を持つマイグレーションクラス設計を確定 + - DBバージョン管理テーブルを定義・運用可能にする +- 非対象(やらないこと): 個別機能のスキーマ最適化 +- 依存関係: CLI機能拡充 +- ExecPlan: `なし` +- メモ/判断ログ: 実装前にExecPlan作成が必要 + +### オンラインアップデート機構(基本設計) +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: 将来の自動更新に向けた安全な更新フローの基本設計を確立する +- 背景/課題: 更新運用が手作業依存で、手順の再現性とロールバック設計が不足している +- 到達条件(Definition of Done): + - 更新対象・配布単位・検証・ロールバックを含む基本設計を定義 + - 既存運用との互換性と段階導入方針を明文化 +- 非対象(やらないこと): 本番運用向けの完全自動更新実装 +- 依存関係: マイグレーション機構 +- ExecPlan: `なし` +- メモ/判断ログ: 基本設計タスクとして扱う + +### 管理操作ログ機構の改修 +- Status: `BLOCKED` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: 監査要件に対応できる管理操作ログ基盤へ移行する +- 背景/課題: `manager_log` は構造化と長期運用に課題があり、監査観点で改善余地が大きい +- 到達条件(Definition of Done): + - JSONLinesで `temp/logs/manager/YYYY/MM/` 保存が可能 + - 管理画面「管理操作ログ」UIを提供 + - CLI拡張(`log:tail manager`, `log:search manager`)を提供 + - `manager_log`依存の段階廃止方針を実装 +- 非対象(やらないこと): システムログの再改修 +- 依存関係: システムログ機構の改修 +- ExecPlan: `.agent/plans/2026-02-07-manager-log-refactor.md` +- メモ/判断ログ: 現在は方針検討中。システムログ改修完了後に着手 + +## 2. ルーティング先行計画(v1.3.0 後半) 目標アーキテクチャ: - フロント・管理画面・APIを単一フロントコントローラへ段階統合する - 当面は `api.php` 先行導入で移行し、互換期間を経て統合する -- [ ] **Phase 0: API Router基盤** - - [ ] `api.php` をフロントコントローラ化 - - [ ] ルート登録/ディスパッチャ/予約パス優先ルール - - [ ] namespace省略解決(`/api/v1/...` -> `/api/evo/v1/...`) - - [ ] ExecPlan: `.agent/plans/2026-02-14-api-router-foundation.md` -- [ ] **Phase 0.5: 管理画面URL変更機能** - - [ ] `manager_prefix` 設定化(`.env`/設定ファイル) - - [ ] 旧 `manager/` 導線の移行挙動定義 - - [ ] Router優先ルールとの衝突回避 - - [ ] ExecPlan: `.agent/plans/2026-02-14-manager-url-routing-migration.md` -- [ ] **Phase 0.8: `manager` 公開URL廃止(段階移行)** - - [ ] 旧URL互換導線と停止条件定義 - - [ ] 旧URL利用の監視ログ導入 - - [ ] 公開URL廃止後の物理ディレクトリ整理 - - [ ] ExecPlan: `.agent/plans/2026-02-14-manager-public-endpoint-retirement.md` -- [ ] **Phase 1: REST API基盤とセキュリティ** - - [ ] `/api/v1/...` 優先(`api.php` はフォールバック) - - [ ] 統一JSONエラー/認証/レート制限/監査ログ - - [ ] ExecPlan: `.agent/plans/2026-02-14-rest-api-foundation-security.md` -- [ ] **Phase 2: Headless公開Read API** - - [ ] `resources` / `media` read-only API - - [ ] ページング/フィルタ/fields - - [ ] 非公開データ遮断 - - [ ] ExecPlan: `.agent/plans/2026-02-14-headless-read-api.md` -- [ ] **Phase 3: 管理操作Write API** - - [ ] resource の create/update/publish/unpublish/delete - - [ ] `hasPermission()` と同一ルール適用 - - [ ] 失敗時監査ログと回復導線 - - [ ] ExecPlan: `.agent/plans/2026-02-14-manager-write-api.md` - -### 3. 大規模改修(v1.4.0 以降) - -- [ ] **PDO移行(最高優先)** - - [ ] `DBAPI` のPDOラッパー実装 - - [ ] 既存 `mysql_` 系互換レイヤー整理 -- [ ] **frame要素廃止(最高優先)** - - [ ] HTML5 + Ajax + Flexbox/Grid へ段階移行 - - [ ] ヘッダー/サイドバー/メインエリア移行 -- [ ] **jQuery廃止(高優先)** - - [ ] Vanilla JS (ES6+) へ段階移行 - - [ ] `querySelector` / `fetch` 活用 +### Phase 0: API Router基盤 +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: APIと後続ルーティング統合の共通土台を先行整備する +- 背景/課題: 現在はルーティング責務が分散し、後続フェーズの実装効率が低い +- 到達条件(Definition of Done): + - `api.php` をフロントコントローラとして機能させる + - ルート登録/ディスパッチャ/予約パス優先ルールを実装 + - namespace省略解決(`/api/v1/...` -> `/api/evo/v1/...`)を実装 +- 非対象(やらないこと): 認証・レート制限などセキュリティ層の本実装 +- 依存関係: CLI機能拡充 +- ExecPlan: `.agent/plans/2026-02-14-api-router-foundation.md` +- メモ/判断ログ: ルーティング先行戦略で段階統合 + +### Phase 0.5: 管理画面URL変更機能 +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: 管理画面URLを設定可能にし、将来の単一入口化へ備える +- 背景/課題: 固定URL前提では衝突回避と運用柔軟性が不足する +- 到達条件(Definition of Done): + - `manager_prefix` を設定化(`.env`/設定ファイル) + - 旧 `manager/` 導線の移行挙動を定義 + - Router優先ルールとの衝突を回避 +- 非対象(やらないこと): `manager` 公開URLの完全廃止 +- 依存関係: Phase 0 +- ExecPlan: `.agent/plans/2026-02-14-manager-url-routing-migration.md` +- メモ/判断ログ: Router連動で前倒し実装する + +### Phase 0.8: `manager` 公開URL廃止(段階移行) +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: `manager` の公開URL依存を解消し、単一入口方針へ移行する +- 背景/課題: 直接公開URLは運用・監視・統合方針と衝突しやすい +- 到達条件(Definition of Done): + - 旧URL互換導線と停止条件を定義 + - 旧URL利用の監視ログを導入 + - 公開URL廃止後の物理ディレクトリ整理計画を確立 +- 非対象(やらないこと): 初期段階での物理ディレクトリ即時削除 +- 依存関係: Phase 0.5 +- ExecPlan: `.agent/plans/2026-02-14-manager-public-endpoint-retirement.md` +- メモ/判断ログ: URL廃止と物理整理は段階分離する + +### Phase 1: REST API基盤とセキュリティ +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: 公開APIと管理APIに共通するセキュアな基盤を確立する +- 背景/課題: 統一エラー・認証・制限・監査の共通実装が未整備 +- 到達条件(Definition of Done): + - `/api/v1/...` 優先運用(`api.php` フォールバック)を実装 + - 統一JSONエラー、認証、レート制限、監査ログを実装 +- 非対象(やらないこと): read/write API個別機能の完結 +- 依存関係: Phase 0 +- ExecPlan: `.agent/plans/2026-02-14-rest-api-foundation-security.md` +- メモ/判断ログ: セキュリティ層を初期段階で固定する + +### Phase 2: Headless公開Read API +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: Headless運用に必要な公開read APIを提供する +- 背景/課題: 既存取得処理は公開向け契約が曖昧で、非公開情報の遮断設計が必要 +- 到達条件(Definition of Done): + - `resources` / `media` のread-only APIを提供 + - ページング/フィルタ/fields選択を提供 + - 非公開データを遮断し、境界値検証を完了 +- 非対象(やらないこと): 更新系API(write) +- 依存関係: Phase 1 +- ExecPlan: `.agent/plans/2026-02-14-headless-read-api.md` +- メモ/判断ログ: 軽量レスポンスと公開境界を重視 + +### Phase 3: 管理操作Write API +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: 管理操作をAPI経由で安全に実行可能にする +- 背景/課題: 既存管理画面依存の更新フローを外部連携可能な形へ整理する必要がある +- 到達条件(Definition of Done): + - resourceのcreate/update/publish/unpublish/delete APIを提供 + - `hasPermission()` と同一権限ルールを適用 + - 失敗時監査ログと回復導線を実装 +- 非対象(やらないこと): 業務特化ロジックの本体組み込み +- 依存関係: Phase 1, Phase 2 +- ExecPlan: `.agent/plans/2026-02-14-manager-write-api.md` +- メモ/判断ログ: 基本CRUDに責務を限定し拡張は分離する + +## 3. 大規模改修(v1.4.0 以降) + +### PDO移行(最高優先) +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: DBアクセス層をPDOへ移行し、互換性と保守性を向上させる +- 背景/課題: 既存 `mysql_` 系互換レイヤーは将来的な保守負担が高い +- 到達条件(Definition of Done): + - `DBAPI` のPDOラッパーを実装 + - 既存 `mysql_` 系互換レイヤーを整理 +- 非対象(やらないこと): 全機能一括置換 +- 依存関係: マイグレーション機構 +- ExecPlan: `なし` +- メモ/判断ログ: 影響範囲が大きいため段階移行を前提 + +### frame要素廃止(最高優先) +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: 管理画面をモダン構成へ移行し、保守性とUXを改善する +- 背景/課題: frame依存構造は拡張性・互換性・開発効率に制約が大きい +- 到達条件(Definition of Done): + - HTML5 + Ajax + Flexbox/Gridへの段階移行計画を実装 + - ヘッダー/サイドバー/メインエリアの移行を完了 +- 非対象(やらないこと): デザイン全面刷新 +- 依存関係: API Router基盤 +- ExecPlan: `なし` +- メモ/判断ログ: URL/ルーティング方針と合わせて段階実施 + +### jQuery廃止(高優先) +- Status: `NEXT` +- 着手予定日: `未定` +- 完了日: `未完了` +- 目的: フロント実装をVanilla JSへ統一し、依存削減と可読性向上を図る +- 背景/課題: jQuery依存はモダン実装との混在コストが高い +- 到達条件(Definition of Done): + - Vanilla JS (ES6+) への段階移行を進める + - `querySelector` / `fetch` ベースへ置換する +- 非対象(やらないこと): UIコンポーネント刷新 +- 依存関係: frame要素廃止 +- ExecPlan: `なし` +- メモ/判断ログ: 移行時は既存挙動の互換維持を優先 diff --git a/.codex/skills/exec-plan/SKILL.md b/.codex/skills/exec-plan/SKILL.md index 86d4cacd6..a5bd99425 100644 --- a/.codex/skills/exec-plan/SKILL.md +++ b/.codex/skills/exec-plan/SKILL.md @@ -8,6 +8,15 @@ description: ExecPlan(実行計画)の作成・検証・更新を支援す `.agent/PLANS.md` の仕様に準拠した ExecPlan を作成・管理するワークフロー。 コーディング規約・ドキュメントマップは `AGENTS.md` を参照。 +## ロードマップ連携(必須) + +1. `.agent/roadmap.md` に記載されたタスクには、必ず対応するExecPlanを持たせる。 +2. `/create-plan` でロードマップ対象のExecPlanを新規作成した場合は、対応タスクの `ExecPlan:` 行へ反映する(未記載の場合)。 +3. 紐付くExecPlanを完了した場合、同一タスクの `Status` を `DONE` に更新し、`完了日` を更新する。 +4. 着手した時点で `Status` を `WIP` に更新し、`着手予定日` が `未定` なら当日を設定する。 +5. ロードマップ上で対応タスクを一意に特定できない場合は、推測で更新せずエンジニアへ確認する。 +6. 完了したExecPlanは `.agent/plans/archive/` へ移動し、ファイル名先頭の日付を完了日(`YYYY-MM-DD`)へ更新する。必要ならロードマップの `ExecPlan:` パスを更新する。 + ## コマンド ### /create-plan <タスク概要> @@ -18,7 +27,8 @@ description: ExecPlan(実行計画)の作成・検証・更新を支援す 4. `.agent/PLANS.md` テンプレートに従い `.agent/plans/YYYY-MM-DD-task-name.md` を作成 全12セクション記載、Progress以外は散文、CMS用語を定義、Validationは観察可能な動作で定義 空セクションは見出しのみ残す(プレースホルダ説明は書かない) -5. `/validate-plan` を自動実行 +5. ロードマップ対象タスクの場合のみ、`.agent/roadmap.md` の対応タスクへ `ExecPlan:` 行を反映し、必要なら `Status: WIP` / `着手予定日` を更新 +6. `/validate-plan` を自動実行 トークン効率の原則(精度優先): - 実装精度・再現性を落とさない範囲で簡潔に書く(必要十分な情報量を維持) @@ -43,6 +53,9 @@ description: ExecPlan(実行計画)の作成・検証・更新を支援す 3. Decision Log に日付・著者・根拠・代替案を記録 4. 完了マイルストーンの Progress 詳細を1行の要約に圧縮(トークン節約) 5. コア側の課題(UI結合・設計上の制約・技術的負債等)を発見した場合は `assets/docs/core-issues.md` に追記(発見日・発見元・ファイル・課題・改善案・関連ロードマップ) +6. 当該ExecPlanがロードマップ対象で完了条件を満たした場合、`.agent/roadmap.md` の対応タスクを `Status: DONE` / `完了日: 当日` に更新する +7. ロードマップ対象で完了条件を満たしていない場合でも、着手中なら `Status: WIP` を維持する +8. 完了条件を満たしたExecPlanは `.agent/plans/archive/` へ移動し、ファイル名先頭の日付を完了日(`YYYY-MM-DD`)へ更新する。必要なら `.agent/roadmap.md` の `ExecPlan:` パスを移動先へ更新する ## 意思決定の閾値 diff --git a/.codex/skills/exec-plan/agents/openai.yaml b/.codex/skills/exec-plan/agents/openai.yaml index 5efe67162..de16bfa25 100644 --- a/.codex/skills/exec-plan/agents/openai.yaml +++ b/.codex/skills/exec-plan/agents/openai.yaml @@ -13,7 +13,8 @@ interface: 6) 不具合対応ではエラー隠蔽を避け、原因データの発生源を修正する方針を明記する。 7) 実装者が過去チャットを参照しなくても実行できる内容にする(hidden context を持ち込まない)。 8) 実装精度を落とさない範囲でトークンを節約する。重複説明を避け、長大なコード全文は原則書かず、必要箇所と参照先パスで表現する。 - 9) 作成後に `/validate-plan` 相当の自己検証を実施し、不足があれば同一ファイルを修正する。 + 9) ロードマップ対象タスクの場合のみ、`.agent/roadmap.md` の `ExecPlan:` 行を反映し、着手時は `Status: WIP` と日付項目を更新する。 + 10) 作成後に `/validate-plan` 相当の自己検証を実施し、不足があれば同一ファイルを修正する。 `/validate-plan [path]`: 1) 対象 ExecPlan を `references/quality-checklist.md` で検証する。 @@ -27,3 +28,6 @@ interface: 3) `Decision Log` に日付・根拠・代替案を追記する。 4) 進捗反映時に重複説明を削除し、不要に長い記述を簡潔化する(根拠・再現性は維持)。 5) 必要に応じて `Validation and Acceptance` / `Idempotence and Recovery` を現状に合わせて更新する。 + 6) 紐付くロードマップ項目がある場合、完了時は `Status: DONE` と `完了日` を更新する。未完了時は `Status: WIP` を維持する。 + 7) 完了したExecPlanは `.agent/plans/archive/` へ移動し、ファイル名先頭の日付を完了日(`YYYY-MM-DD`)へ更新する。必要ならロードマップの `ExecPlan:` パスを移動先へ更新する。 + 8) 対応タスクを一意に特定できない場合は、推測で更新せず確認を求める。 diff --git a/.codex/skills/roadmap-manager/SKILL.md b/.codex/skills/roadmap-manager/SKILL.md new file mode 100644 index 000000000..d32cecf30 --- /dev/null +++ b/.codex/skills/roadmap-manager/SKILL.md @@ -0,0 +1,94 @@ +--- +name: roadmap-manager +description: ロードマップ(`.agent/roadmap.md`)を運用するスキル。タスクの追加・変更・削除・次タスク着手・完了同期を一貫して扱い、ExecPlan未作成タスクは着手前に計画を作成する。 +--- + +# Roadmap Manager + +`.agent/roadmap.md` をSSOTとして、ロードマップの保守と実行を行う。 +実装規約は `AGENTS.md` を最優先とする。 + +## 記述フォーマット(固定) + +ロードマップ項目は必ず次の形で記述する。 + +```md +### <タスク名> +- Status: `NEXT | WIP | DONE | BLOCKED` +- 着手予定日: `YYYY-MM-DD` または `未定` +- 完了日: `YYYY-MM-DD` または `未完了` +- 目的: +- 背景/課題: +- 到達条件(Definition of Done): +- 非対象(やらないこと): +- 依存関係: +- ExecPlan: `.agent/plans/YYYY-MM-DD-task-name.md` または `なし` +- メモ/判断ログ: +``` + +運用制約: +- ロードマップでは実装手順の箇条書きを持たない(手順はExecPlanへ集約) +- 進捗管理は `Status` を正とし、チェックボックスは互換表示が必要な場合のみ使う +- 追加・更新・削除時は上記全項目を欠落させない +- 日付欄が未確定の場合は `未定` / `未完了` を使う + +## 実行ルール + +1. 正本は `.agent/roadmap.md` のみを更新する。 +2. 並び順は依存順を維持し、タスク追加時も依存関係が読める位置へ配置する。 +3. 着手系操作では、対象タスクに ExecPlan が無ければ先に作成する。 +4. タスク完了時は `Status: DONE` に更新し、必要なら親タスクも完了状態へ更新する。 +5. 変更系操作(追加/変更/削除)では、関連する ExecPlan パスも同時に整合させる。 +6. `最終更新` は変更が発生した日付へ更新する。 + +## コマンド + +### /roadmap-next +1. 依存順で次の未完了タスクを1件選定する。 +2. ExecPlan 行を確認し、無ければ `.agent/PLANS.md` 準拠で新規作成して `ExecPlan:` 行を追記する。 +3. ExecPlan の `Progress` 初期行を更新して着手する。 + +### /roadmap-add <セクション> <タスク> +1. 指定セクション配下へ固定フォーマットでタスクを追加する。 +2. 実装タスクの場合は `ExecPlan:` 行を追加し、対応プランを作成する。 +3. 依存順が崩れないかを確認する。 + +### /roadmap-update <対象> <変更内容> +1. 対象タスクの `着手予定日` `完了日` `目的` `背景/課題` `到達条件` `非対象` `依存関係` `メモ/判断ログ` を更新する。 +2. 既存 ExecPlan の目的・検証条件と矛盾しないよう同期する。 +3. 変更後も固定フォーマットが保たれていることを確認する。 + +### /roadmap-remove <対象> +1. 対象タスクをロードマップから削除する。 +2. 対応 ExecPlan が存在する場合は削除せず、`Outcomes & Retrospective` に中止理由を追記してアーカイブ扱いにする。 +3. 親子関係と番号構造を整える。 + +### /roadmap-sync +1. 実装・検証結果に基づき `Status` を `NEXT/WIP/DONE/BLOCKED` へ更新する。 +2. `Status: DONE` に変更した項目は `完了日` を当日に更新する(未完了状態へ戻す場合は `未完了`)。 +3. 互換表示としてチェックボックスが残っている場合のみ整合させる。 +4. `最終更新` を当日に更新する。 + +### /roadmap-normalize +1. 旧ToDo形式の項目を固定フォーマットへ変換する。 +2. 変換時に実装手順を `到達条件` と `メモ/判断ログ` へ再配置し、詳細は ExecPlan 参照へ寄せる。 +3. 変換後に `Status` と `ExecPlan` の欠落がないことを確認する。 + +## 参照順(最小) + +1. `AGENTS.md` +2. `.agent/roadmap.md` +3. `.agent/PLANS.md` +4. `assets/docs/architecture.md`(影響が大きい場合) + +## 意思決定の閾値 + +**自律判断可能**: +- 依存順を維持した文言修正 +- 完了チェック同期 +- ExecPlan の有無判定と新規作成 + +**要相談**: +- 優先順位の大幅変更 +- セクション再編(章立て変更) +- 複数タスクの一括削除 diff --git a/.codex/skills/roadmap-manager/agents/openai.yaml b/.codex/skills/roadmap-manager/agents/openai.yaml new file mode 100644 index 000000000..afc28935b --- /dev/null +++ b/.codex/skills/roadmap-manager/agents/openai.yaml @@ -0,0 +1,11 @@ +interface: + display_name: "Roadmap Manager" + short_description: "ロードマップの追加・変更・削除・着手・完了同期を管理する" + default_prompt: | + 以下の順序で進めてください。 + 1) `.agent/roadmap.md` を正本として現在状態を確認する。 + 2) 依頼種別(追加 / 変更 / 削除 / 次タスク着手 / 完了同期)を判定する。 + 3) タスク記述は固定フォーマット(Status/着手予定日/完了日/目的/背景/到達条件/非対象/依存関係/ExecPlan/メモ)を必ず使う。 + 4) 着手対象に ExecPlan が無ければ `.agent/PLANS.md` 準拠で先に作成し、ロードマップへ `ExecPlan:` 行を追記する。 + 5) ロードマップと ExecPlan の整合を保ったまま更新する。 + 6) 完了済み項目は `Status: DONE` へ反映し、`.agent/roadmap.md` の `最終更新` を当日に更新する。 diff --git a/.codex/skills/roadmap-next-task/SKILL.md b/.codex/skills/roadmap-next-task/SKILL.md new file mode 100644 index 000000000..f1e2b9bb2 --- /dev/null +++ b/.codex/skills/roadmap-next-task/SKILL.md @@ -0,0 +1,59 @@ +--- +name: roadmap-next-task +description: ロードマップ(`.agent/roadmap.md`)の依存順を基準に次の未完了タスクへ着手するスキル。完了時のチェック反映、ExecPlan未作成タスクの計画作成先行、実装開始までを一貫して行う。 +--- + +# Roadmap Next Task + +`.agent/roadmap.md` をSSOTとして、次に着手すべきタスクを選定し、必要なら ExecPlan を作成してから実装に入る。 +実装規約は `AGENTS.md` を最優先とする。 +ロードマップ全体の追加・変更・削除や記述フォーマットの維持は `roadmap-manager` を使い、このスキルは「次タスク着手」に限定する。 + +## 実行ルール + +1. 正本は必ず `.agent/roadmap.md` を使う(`assets/docs/roadmap.md` は案内用途)。 +2. タスク選定は「実行順ロードマップ(依存順)」の上から順に行う。 +3. 既に完了している作業を見つけた場合は、実装前にロードマップのチェック状態を同期する。 +4. 着手対象タスクに ExecPlan が無い場合は、実装前に `.agent/PLANS.md` 準拠で新規作成する。 +5. ExecPlan がある場合でも、着手前に目的・進捗・検証条件を更新する。 +6. 実装完了時は、対応タスクの `Status` を `DONE` に更新し、`完了日` を当日に更新する。 +7. チェック更新時は `最終更新` 日付も当日に更新する。 + +## コマンド + +### /next-task +1. `.agent/roadmap.md` の未完了項目を依存順で確認し、最上位の次タスクを1件特定する。 +2. 対象タスクに `ExecPlan:` 行があるか確認する。 +3. `ExecPlan:` 行が無い場合、`.agent/plans/YYYY-MM-DD-task-name.md` を作成し、該当タスク配下へ `ExecPlan:` 行を追記する。 +4. 作成済み/新規の ExecPlan を更新し、最初の実装ステップを `Progress` に追加する。 +5. 実装に着手する。 + +### /sync-roadmap +1. 直近の実装結果・テスト結果から完了条件を満たした項目を抽出する。 +2. `.agent/roadmap.md` の該当タスクの `Status` を `DONE` に更新し、`完了日` を当日に更新する。 +3. 互換表示としてチェックボックスが残っている項目がある場合のみ整合させる。 +4. `最終更新` を当日に更新する。 + +### /finish-task +1. 対象 ExecPlan の `Progress` と `Validation and Acceptance` を完了状態に更新する。 +2. `/sync-roadmap` を実行してロードマップへ完了反映する。 +3. 未完了の次タスク候補を1件提示して終了する。 + +## 参照順(最小) + +1. `AGENTS.md` +2. `.agent/roadmap.md` +3. `.agent/PLANS.md` +4. `assets/docs/architecture.md`(実装影響が大きいとき) + +## 意思決定の閾値 + +**自律判断可能**: +- 次タスクの機械的選定(依存順で先頭の未完了) +- ExecPlan の有無判定と新規作成 +- ロードマップのチェック同期 + +**要相談**: +- 優先順位の入れ替え +- 複数タスク同時着手 +- ロードマップ項目そのものの追加・削除 diff --git a/.codex/skills/roadmap-next-task/agents/openai.yaml b/.codex/skills/roadmap-next-task/agents/openai.yaml new file mode 100644 index 000000000..36da30391 --- /dev/null +++ b/.codex/skills/roadmap-next-task/agents/openai.yaml @@ -0,0 +1,11 @@ +interface: + display_name: "Roadmap Next Task" + short_description: "ロードマップから次タスクを選び、必要ならExecPlanを作って着手する" + default_prompt: | + 以下の順序で進めてください。 + 1) `.agent/roadmap.md` を読み、依存順で次に着手すべき `Status: NEXT` のタスクを1件選定する。 + 2) すでに完了しているのに `Status` や `完了日` が未同期の項目があれば先に `Status: DONE` と `完了日` を同期する。 + 3) 対象タスクに ExecPlan が無ければ `.agent/PLANS.md` 準拠で新規作成し、ロードマップへ `ExecPlan:` 行を追記する。 + 4) ExecPlan の `Progress` と検証手順を更新し、対象タスクを `Status: WIP` にしてから実装に着手する。 + 5) 完了後は対象タスクを `Status: DONE` にし、`完了日` を更新する。必要なら親タスクの `Status` も同期する。 + 6) `.agent/roadmap.md` の `最終更新` を当日に更新する。 diff --git a/.gitignore b/.gitignore index 616ba887d..3613f01d4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,10 @@ /manager/includes/config.inc.php /manager/includes/extra.config.php +# 個人操作履歴 +.bash_history +**/.bash_history + # システムが動的に生成するサーバ固有のファイルのため同期が不要なファイル・ディレクトリ .thumbs/ /temp/cache/* diff --git a/compose.yml b/compose.yml new file mode 100644 index 000000000..fb31c7dc4 --- /dev/null +++ b/compose.yml @@ -0,0 +1,54 @@ +services: + app: + build: + context: . + dockerfile: ./manager/docker/Dockerfile + args: + USER_ID: ${UID:-1000} + GROUP_ID: ${GID:-1000} + container_name: app-php8 + ports: + - "80:80" + volumes: + - ./:/var/www/html + - ./manager/docker/php.ini:/usr/local/etc/php/php.ini + - ./manager/docker/msmtprc:/etc/msmtprc:ro + environment: + - APACHE_RUN_USER=www-data + - APACHE_RUN_GROUP=www-data + depends_on: + - db + - mailpit + networks: + - evo_net + + db: + image: mysql:8.3 + container_name: db-mysql8 + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-password} + MYSQL_DATABASE: ${MYSQL_DATABASE:-app-php8} + MYSQL_USER: ${MYSQL_USER:-user} + MYSQL_PASSWORD: ${MYSQL_PASSWORD:-password} + volumes: + - db_data_mysql:/var/lib/mysql + ports: + - "3306:3306" + networks: + - evo_net + + mailpit: + image: axllent/mailpit:latest + container_name: mailpit + ports: + - "1025:1025" + - "8025:8025" + networks: + - evo_net + +networks: + evo_net: + driver: bridge + +volumes: + db_data_mysql: diff --git a/manager/docker/.bashrc b/manager/docker/.bashrc new file mode 100644 index 000000000..9cec5b0fb --- /dev/null +++ b/manager/docker/.bashrc @@ -0,0 +1,6 @@ +#!/bin/bash + +HISTCONTROL=ignoredups:erasedups +export PS1='\n \[\e[1;32m\]\w \n \[\e[1;32m\]> \[\e[m\]' +export HISTFILE=~/.bash_history +touch $HISTFILE diff --git a/manager/docker/Dockerfile b/manager/docker/Dockerfile new file mode 100644 index 000000000..b1c0983bc --- /dev/null +++ b/manager/docker/Dockerfile @@ -0,0 +1,28 @@ +FROM php:8.4-apache + +ARG USER_ID=1000 +ARG GROUP_ID=1000 + +# 依存パッケージとPHP拡張 +RUN apt-get update && apt-get install -y \ + wget curl vim net-tools iputils-ping unzip \ + libpng-dev libjpeg-dev libfreetype6-dev \ + libzip-dev libxml2-dev libicu-dev libcurl4-openssl-dev \ + libonig-dev libxslt1-dev libexif-dev \ + msmtp msmtp-mta \ + && docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install gd mysqli curl mbstring zip xml opcache intl bcmath soap exif \ + && a2enmod rewrite \ + && rm -rf /var/lib/apt/lists/* + +# 権限調整 +RUN groupmod -g ${GROUP_ID} www-data && \ + usermod -u ${USER_ID} -g www-data www-data && \ + mkdir -p /var/www/html && chown -R www-data:www-data /var/www/html + +# PHPからmsmtpを使うよう設定 +RUN echo 'sendmail_path = "/usr/bin/msmtp -t -i"' > /usr/local/etc/php/conf.d/msmtp.ini && \ + ln -sf /usr/bin/msmtp /usr/sbin/sendmail + +# Apache起動 +CMD ["apache2-foreground"] diff --git a/manager/docker/msmtprc b/manager/docker/msmtprc new file mode 100644 index 000000000..c2dc8a377 --- /dev/null +++ b/manager/docker/msmtprc @@ -0,0 +1,7 @@ +account default +host mailpit +port 1025 +from noreply@example.com +auth off +tls off +logfile /tmp/msmtp.log diff --git a/manager/docker/php.ini b/manager/docker/php.ini new file mode 100644 index 000000000..025f00ac2 --- /dev/null +++ b/manager/docker/php.ini @@ -0,0 +1,11 @@ +upload_max_filesize = 64M +post_max_size = 64M +memory_limit = 128M + +display_errors = Off +log_errors = On +error_reporting = E_ALL + +date.timezone = Asia/Tokyo + +; extension=mysqli