wi-app について
wi-appは、wonder-image/appを単独サイトではなくComposerのフレームワークパッケージとして扱うためのエージェントスキルです。変更がフレームワーク、サイト、外部モジュールのどこに属するかを判断し、設計やセキュリティの規約に沿って作業できます。
主な機能
- 01フレームワーク、サイト、モジュールの区別
- 02タスクに応じた設計資料の案内
- 03モデルとリソースの拡張規則
- 04API、CSRF、セキュリティ規約の説明
活用シーン
- 01編集前の変更対象の分類
- 02タスクに合うフレームワーク資料の検索
- 03コンポーネントやAPI変更の配置・検証規則の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wonder-image/ skills --skill wi-appインストール後、Claude Code で/wi-appを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/architecture.mdcomponent-catalogue.mdmodel-and-resource.mdpermissions-and-users.mdscheduler.mdsecurity.mdworkflows.md詳細
Wonder Image App
概要
このスキルは、wonder-image/app を単独のアプリではなく、フレームワークパッケージとして扱う際に使用します。コードを変更したり、コマンドを実行したり、新しいロジックの配置先を判断したりする前に、フレームワークとサイトの境界を明確にしてください。
用語集
wi-app と wi-site で共通の用語です(両方のスキルで同じ表現を使用します)。
- フレームワーク —
wonder-image/app(Composer パッケージ、github.com/wonder-image/app)。wi-app が有効な場合はリポジトリのルートにあり、サイト内ではvendor/wonder-image/app/にあります。 - lib —
wonder-image/lib(npm パッケージ、github.com/wonder-image/lib)。JS / CSS デザインシステムです。ソースはnode_modules/wonder-image/src/、コンパイル済みのコピーはassets/lib/wonder-image/dist/にあります。 - スキャフォールド —
wonder-image/new-site(github.com/wonder-image/new-site)。サイトのテンプレートです。スキャフォールド自体も有効なサイトです。 - サイト —
wonder-image/appに依存するcomposer.jsonを持つプロジェクト(つまり、フレームワークをvendor/wonder-image/appにインストールするプロジェクト)です。通常はスキャフォールド、またはスキャフォールドから派生したプロジェクトです。正式な用語です。「コンシューマープロジェクト」/「コンシューマーアプリ」など、以前の混在した表現より「サイト」を優先してください。 - モジュール — Composer(またはファイルシステムのフォールバック)経由で検出される外部 Composer パッケージ
wonder-image/<slug>です。module.jsonとModuleInterfaceのエントリポイントを通じて、独自のモデル/リソース/ルートを提供します。 custom/— プロジェクトのページ、コンポーネント、レイアウト、ルート、設定、ヘルパー用のサイト専用ディレクトリです。フレームワーク内には存在しません。app/Models/app/Resources— サイトの PSR-4 ルート(App\Models\.../App\Resources\...)です。フレームワークのclass/App/Models/class/App/Resources(Wonder\App\Models\.../Wonder\App\Resources\...)とは別です。
wi-site に切り替える場合
次のいずれかに該当する場合は wi-site に切り替えてください。作業対象はフレームワークではなく、サイトのリポジトリです。
- リポジトリの
composer.jsonで"name": "wonder-image/app"が宣言されていない場合。代わりにrequireにwonder-image/appが含まれています(フレームワークは依存関係としてインストールされています)。 - Wonder サイト(
site_type: landing/corporate/blog/ecom/rsvp)を宣言するdocs/ai/PRODUCT.mdが存在する場合(まだ移行されていないサイトでは、リポジトリのルートにあるPRODUCT.md)。このファイルはサイトにのみ存在し、フレームワーク自体の内部にはありません。 - リポジトリのルートに
vendor/wonder-image/app/が存在する場合。フレームワークがvendor/の下にインストールされているため、これはサイトです。 - 変更依頼の対象が
custom/、app/Models、app/Resources、lang/、assets/{ASSETS_VERSION}/、またはフレームワークリポジトリ内に存在しないパスの場合。 - タスクが「ページを追加する」「文字列を翻訳する」「このサイトに権限キーを登録する」「色のトークンを編集する」「
.wi-*コンポーネント/lib クラスを使用する」、またはフレームワークを拡張するのではなく使用する作業の場合。 vendor/wonder-image/app/の下にあるファイルを修正しようとしている場合。修正してはいけません。変更内容をcustom//app/に配置する形に変更するか(この場合も wi-site)、フレームワークリポジトリ自体に対する変更として作業してください(その場合は wi-app が適用されます)。
まず確認すること
- 編集を始める前に、依頼の種類を判定します。
- 変更対象がフレームワーク、サイト、外部モジュールパッケージのいずれに該当するか判断します。
- タスクに該当するリファレンスファイルだけを読みます。
- ブートストラップ、レジストリ、ルート、環境変数の解決、モジュールの読み込みについては
references/architecture.md - Model / Resource 拡張 API、スキーマ、リピーターフィールド、
CustomPageSchemaについてはreferences/model-and-resource.md - 権限ビルダー API、権限キー、共通ユーザー管理リソースについては
references/permissions-and-users.md - 変更の配置先、検証、よくある落とし穴については
references/workflows.md - CSRF、Cookie、認証ヘルパー、アップロード、リダイレクト、エクスポート、SQL エスケープ、エラー/ログの衛生管理、バックアップ、同意については
references/security.md
- ブートストラップ、レジストリ、ルート、環境変数の解決、モジュールの読み込みについては
基本ルール
wonder-image/appは Composer ライブラリとして扱ってください。実際のランタイムは、これをvendor/wonder-image/appにインストールするサイト側にあります。php forge ...コマンドは、別途確認できない限りサイト側のコマンドとして扱ってください。このパッケージのルートにforge実行ファイルがあるとは考えないでください。- 新しいロジックには
class/App/*を優先して使ってください。レガシーのapp/*に手を加えるのは、ランタイムが引き続き依存している場合に限ります。 - API ハンドラーは
app/http/api/*にあります。パッケージのハンドラーをapp/api/*に再導入せず、ルーティング済みの/api/...エンドポイントはPath::$api、Path::$appApi、Path::$apiDTを介して呼び出してください。 - API ベアラーの検証は
Wonder\Api\Token\BearerVerifierが行います(署名、exp、api_users.tokenに対するhash_equals、権限、IP/ドメイン)。JWT を手動でデコードせず、これを再利用してください。トークンの発行にはApiTokens::issue()、ローテーションにはregenerateApiToken()を使ってください。ベアラーを HTML に出力してはいけません(Credentials::appToken()、ApiTokens::pageToken())。ページではconst API_TOKEN = '';を出力し、ライブラリは空のAuthorizationを省略します。ページトークンを許可するエンドポイントへのベアラーなしのリクエストは、Endpoint::sessionRequestAllowed()が成立する場合(同一オリジン、有効なセッション、GET/HEAD 以外ではCsrf::verify())かつBearerVerifier::verifySession()を通過すると、@systemのページアクセスになります。この場合、isPageToken()はtrueとなり、行の可視性にはセッションユーザーが使われます。有効期限後に更新するには、サイトページで新しい CSRF トークン(/api/csrf/)を取得し、_csrfと<meta name="wi-csrf">を更新します。/api/token/page/は互換性のためだけに残されています。サーバー専用エンドポイント(デプロイ、cron、外部トリガー)では、Handler::run()にallowPageToken: falseを渡してください。api_activityに保存されるのはApiTokens::fingerprint()のみです。詳しくはdocs/app/piattaforma/api.md#tokenを参照してください。 - ランタイムのフォールバックとシードのペイロードは分けてください。
Wonder\\App\\RuntimeDefaultsは、レンダリング時やインメモリ設定の構成時に使うランタイムのデフォルト値用です。Wonder\\App\\SeedDefaultsは、build/row、セットアップコマンド、シードを元にするシングルトンフォームで使う、冪等なブートストラップ/シードのペイロード用です。
- 将来の統合や拡張を考慮してプログラミングしてください。目の前のローカルな用途だけを解決するのではなく、サイトや外部モジュールで再利用、拡張、オーバーライド、統合できるクラスや関数の設計を優先してください。
- アーキテクチャの役割分担を明確に保ってください。
Model::tableSchema()は SQL 構造を定義しますModel::dataSchema()はデータの準備と永続化の動作を定義しますResource::formSchema()はバックエンドの入力項目を定義しますCustomPageSchemaは CRUD 以外のバックエンドページを扱いますRepeaterは繰り返し可能な行と関連行の同期を扱います
- フォーム入力は必ず
FormField階層を経由させてください。 フロントエンドの Wonder テーマ(class/Themes/Wonder/)とバックエンドの Bootstrap テーマ(class/Themes/Bootstrap/)のすべての入力項目は、FormField/RepeaterColumn(または型付きのInputs\Input*を直接使用)で宣言し、Input::render($theme)を通じてレンダリングします。生の<input>/<select>/<textarea>HTML や場当たり的なレンダリング関数を使ってはいけません。不足している入力タイプは呼び出し元で場当たり的に修正せず、フレームワーク層に追加します(型付きのInputs\Input*のelement()→FormFieldのヘルパー → 各テーマのレンダラー)。理由と「不足しているタイプ」の 4 ステップの手順についてはreferences/model-and-resource.mdを参照してください。 - Wonder の日付レンダラーは、エスケープ済みの
data-wi-*属性のみでDatePicker、DateRange、DateTimeRange、SelectDateを記述します。jQuery UI の初期化はwonder-image/lib/src/build/frontend/js/form/input.jsのsetInput()で行います。レンダラーが所有するインラインスクリプトにフィールド値や範囲を埋め込んではいけません。 - 翻訳には
Wonder\Localizationを使用してください。Set-up Traduzioni ページでは、TranslationSourceのCatalog(json、legal、model:<table>)をエクスポート/インポートします。モジュールはlocalization.sourcesでソースを追加でき、サイトはCatalog::set()で追加できます。falseを指定すると削除されます。インポートはプレビューされ、サーバー側に保存され、キーを削除することはありません。翻訳可能なモデルはTranslatableとHasTranslationsを実装し、Model::translated($rows, $lang)で読み取ります。値はステータスautomatic/reviewed/reviewとともにtranslationsに保存され、automaticの値を書き込むのはwonder.content-translationのみです(語彙、メモリ、Translatorドライバーを使用)。この処理でreviewedの値が上書きされることはありません。法的文書のソースはlegal_documentsのみです(LegalDocument::make($type))。テストではストアとドライバーを注入し(Translations::useStore())、Google を呼び出さないでください。詳しくはdocs/app/concetti/traduzioni.mdを参照してください。 <wi-card>は廃止されています。 新しい<wi-card>タグを追加したり、新しいコードでwiCard()/wiCardLink()を呼び出したりせず、アプリではCardを使用してください。これは<div class="card">をレンダリングします。<wi-card>を含むページを編集する場合は、その要素を置き換えてください。Cardにタグを変更するオプションを追加してはいけません。既存のページは移行されるまでcreateCard()とライブラリのwi-cardCSS ルールに依存するため、これらは残してください。- セッションの CSRF トークンは
Wonder\Http\Csrf(token()、field()、verify()。フィールドは_csrf、ヘッダーはX-WI-CSRF、wonder-image≥ 2.1.2-alpha.31 のライブラリから送信、ベースレイアウトに<meta name="wi-csrf">)に属します。両テーマのFormレンダラー、Button::post()、POST のDropdown項目、Modal::form()、Resource フォームページは、GET ではなく、アクティブなセッションがある場合に限り、それぞれCsrf::fieldFor()を使ってフィールドを出力します。手書きの<form>タグには、独自にCsrf::field()を追加してください。検証はルートごとに行います。ルートまたはグループに->csrf()を宣言すると、RouteDispatcherはauthorizeUser()の後にWonder\Http\CsrfGuardを実行します(トークンがない、または正しくない場合は 403)。すべての/api/backend/*ルート(alertを除く)にはすでに設定されています。ベアラー専用ルートには設定しません。POST で書き込みを行うページハンドラーは、書き込み前にCsrf::verify()を呼び出し、テキストに "CSRF" または "token" を含めず、アラート929で失敗させてください(ヘルパーはCsrf::ALERT、failureMessage()、oldInput()、flashFailure()、renderCsrfFailure())。GET で操作してはいけません。AuthSessionはCsrfに処理を委譲します。新しい機能固有のトークンを追加しないでください(顧客アカウントモジュールから_contact_csrfは削除され、フォームは_csrfを使用します。Impersonationはスコープ付きトークンを保持します)。詳細とその他のセキュリティ契約についてはreferences/security.mdを参照してください。 - 共有コンポーネントの確認処理には、ライブラリの
data-wi-confirm*契約(Promise<boolean>を返すwi.confirm()。wonder-imageライブラリ ≥ 2.1.2-alpha.31)を使用し、window.confirmや手書きのonclickは使わないでください。ライブラリでは、バックエンドのmodal(text, link, …)はwi.confirm()の@deprecatedエイリアスです。一方、フロントエンドのmodal(selector)はwi.modal.open(id, { title })/wi.modal.close(id)への置き換えが推奨される@deprecated関数です。コア PHP のmodal()(app/function/backend/modal.php)とplugin.phpおよびBackend\Table\Fieldのonclick="modal(...)"は main で削除されています(app#129 の破壊的変更。まだタグには含まれておらず、v2.4.0-beta.5 には残っています)。レガシーの Delete ボタンはdata-wi-confirm*を出力し、ajaxRequestを呼び出すようになりました。新しいコードではmodal()を呼び出したり、#modalを対象にしたりしてはいけません。Button::confirm($message, title:, ok:, variant:)と、confirm、confirm_title、confirm_ok、confirm_variantを持つ Dropdown 項目を使用してください。POST アクションは<form>に指定します(Themes\Concerns\RendersPostFormは CSRF フィールドも出力します)。それ以外はタグに指定します。'method' => 'post'を持つDropdown項目は項目ごとの CSRF フォームであり、action()は href のない<button type="button">です。Modal::form($action, $method, $hidden)は本文とフッターを、Cancel の後に Save が続く CSRF フォームで囲みます(cancel()、submit()。手動のfooter()を指定するとこれらを置き換えます)。Resource レイアウト内では例外LogicExceptionが発生するため、フォームはその外側にレンダリングする必要があります。Bootstrap で単独にレンダリングする場合、columns()/columnSpan()は Resource レイアウトと同じようにフィールドを配置します。日付入力では、スラッシュ区切りの値をd/m/Yとして読み取ります。内側の各パーツには、HasPartAttributes/RendersPartAttributesに基づく公開メソッドを 1 つずつ用意します(Modal::dialogClass()~footerClass()、Dropdown::toggleClass()、menuClass()、itemClass())。クラスはテーマのクラスに追加され、単一のclass属性に出力されます。詳しくはdocs/app/concetti/componenti/README.mdを参照してください。 - 新しいコンポーネントや公開コンポーネント API は、
docs/components/<category>/<slug>.phpにカタログ項目を追加して初めて完成します。php tests/Docs/CatalogRenderTest.phpが成功する必要があります。テーマの対応状況は手作業で記述せず、必ずThemeSupportで計算してください。詳しくはreferences/component-catalogue.mdを参照してください。 - ブートストラップ、アーキテクチャ、ルーティング、レイアウト構造、開発者向けの規約を変更する場合は、同じ作業で
docs/app/*も更新してください。
タスクの振り分け
ブートストラップまたはランタイム
まず references/architecture.md を読み、次に wonder-image.php、class/App/Credentials.php、ルート設定、関連するレジストリを確認してください。ROOT を解決する処理、.env を読み込む処理、または初期ブートストラップの順序を変更する処理には注意してください。
CRUD リソース、バックエンドページ、または API 生成
まず references/model-and-resource.md で Model / Resource の拡張コントラクトを確認し、次に references/architecture.md でレジストリの優先順位とルートの出力を確認してください。その後、Resource::permissionSchema() から参照される権限キーについて、references/permissions-and-users.md を確認してください。
フォーム入力(フロントエンド Wonder またはバックエンド Bootstrap)
references/model-and-resource.md の「FormField hard rule」セクションを読んでください。どちらのテーマでも、すべての入力は FormField::key(...) / RepeaterColumn::key(...) または型付きの Inputs\Input* を通じて宣言し、その後 Input::render($theme) で描画します。新しい入力タイプは class/App/ResourceSchema/Inputs/ に追加し、独自の element() を実装し、FormField にヘルパーを公開して、class/Themes/Wonder/ および class/Themes/Bootstrap/ のレンダラーを使用してください。呼び出し箇所に独自の HTML を記述してはいけません。
デフォルトコンポーネントまたはテーマ内の UI / スタイル
変更が、フレームワークに含まれるデフォルトコンポーネント(class/App/Resources/.../*.php のビュー、class/Elements/Components/ のフォーム以外の Components、class/Elements/Media/ の Media、class/Elements/Form/Components/ のフォーム Components、class/Themes/{Wonder,Bootstrap}/ の Wonder / Bootstrap レンダラー、またはサイトで使用される app/view/... のページ)に関わる場合、UI の正式なルールブックは wi-site/references/style-and-lib.md です。wonder-image/app 内でも、wonder-image/lib を優先して再利用する方針が適用されます。フレームワークレベルで新しい .wi-* 名を独自に作らないでください(これは lib 側の変更です)。デフォルトコンポーネントにサイト固有のトークンを埋め込まず、サイトの color.css / root.css との互換性を維持してください。これには Button、Badge、ButtonGroup、Dropdown などの共有アクションプリミティブも含まれます。共有コンポーネントでリンク属性を扱う場合は、共通の concern class/Elements/Concerns/HasLinkAttributes.php を優先し、テーマレンダラーを薄く保てるよう、href、target、rel、title、onclick、download を attributes に保存してください。この参照をローカルで確認できるよう、wi-app と並行して wi-site をインストールしてください。
コンポーネントカードとカタログ
class/Elements/* の Element またはその公開 API を追加・変更する場合は、カードの場所と形式、検証テスト、カタログの開き方、PageAssets::once()、および lib のバージョン制約について、references/component-catalogue.md を読んでください。
セキュリティ上重要なコード
リクエスト処理、セッション、Cookie、アップロード、エクスポート、リダイレクト、SQL ヘルパー、ロギング、API 認証に手を加える前に、references/security.md を読んでください。各コントラクトを所有するクラスが記載されています。ハンドラーやモジュールでチェックを再実装せず、そのクラスを再利用してください。
権限、ロール、またはユーザー管理
references/permissions-and-users.md を読んでください。ビルダー API(Permissions::reset()、Area::make()、Permission::make())、モジュール権限とのマージ、ランタイムの $PERMITS エクスポート、共有の UserManagementResource / BackendUserResource / ApiUserResource のフローについて説明しています。
モジュールシステム
references/architecture.md を読んでください。Composer による検出、ファイルシステムのフォールバック、有効なモジュールの状態、外部パッケージからのルート / モデル / リソースの登録との互換性を維持してください。
コンソールコマンドまたはローカル起動フロー
スケジュールタスク、cron エントリーポイント、タスクプロバイダー、保持期間、メトリクス、サイトマップの移行、または Google Places の位置情報同期(GoogleReviews)については、references/scheduler.md も読んでください。
references/workflows.md を読んでください。コマンドのソースがこのパッケージにあっても、これらのコマンドはサイトから実行することを想定している点に注意してください。
検証
- 変更したすべての PHP ファイルに対して
php -lでリントを実行します。 - クラスを移動した場合、または新しいクラスを追加した場合は、
composer dumpautoloadを実行します。 - ブートストラップ、ルーティング、コンソールコマンド、リソース、モデル、またはリクエストハンドラーに影響する変更の場合は、サイトから
php forge update --localとphp forge startを実行して検証します。 - 変更が Herd 固有の場合は、
references/workflows.mdに記載されたローカルルーティングの経路も検証します。
出力に関する要件
- 修正がフレームワーク、サイト、モジュールパッケージのどれに属するかを説明します。
- フレームワークを一般的に説明するのではなく、主なファイルと関連するレジストリを明記します。
- フレームワークのルートへの編集がサイトを通じて初めて機能する場合は、統合検証の必要性を明記します。