Skip to content

feat(agent-commerce): エージェントコマース共通基盤 Phase 1a (#6777)#6802

Open
nanasess wants to merge 13 commits into
EC-CUBE:4.4from
nanasess:feature/agentic-commerce-base
Open

feat(agent-commerce): エージェントコマース共通基盤 Phase 1a (#6777)#6802
nanasess wants to merge 13 commits into
EC-CUBE:4.4from
nanasess:feature/agentic-commerce-base

Conversation

@nanasess

@nanasess nanasess commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

概要(Overview・Refs Issue)

エージェントコマース (ACP / UCP) 対応の共通基盤 #6777 のうち、CheckoutSession に依存しない先行スライス (Phase 1a) を実装します。これにより Product Feed / Catalog (#6794) と UCP Discovery (トラック A) が CheckoutSession 中核の完成を待たずに着手・先行リリース可能になります。

方針(Policy)

  • CheckoutSession 非依存の最小集合のみを先行 landing (トラック A 解放)。CheckoutSession 中核・checkout・OAuth2 認証は Phase 1b 以降。
  • 秘密鍵は dtb_baseinfo に置かず app/keystore/<feature>/ に保管 (共通の鍵保管ディレクトリ app/keystore/ の導入 (各種暗号鍵・シークレットの標準置き場) #6797)。解決順は環境変数パス上書き (Secrets Manager / Key Vault 連携) → 既定ファイル (有効化時自動生成・perm 600) = eccube-api4 の OAuth2 鍵と同方式。app/ は web ルート内 (public-dir:".") のため app/keystore/.htaccess deny + ルート .htaccess 拡張子ブロックに key 追加 + nginx /app deny (既存) で多重防御。
  • プライバシーポリシー / 利用規約 URL は BaseInfo カラム化せず、既存標準ページ (help_privacy / help_agreement) から絶対 URL を実行時生成する方針 (本 PR ではマッピング基盤のみ)。
  • 金額は Symfony\Component\Intl\Currencies::getFractionDigits() を再利用 (ゼロデシマル通貨を権威データで処理)、bcmath は既存 nanasess/bcmath-polyfill
  • 国コードは Country::getIsoCode() が存在せず mtb_country.id が ISO 3166-1 numeric のため、numeric→alpha-2 は新規マスタ mtb_country_iso_code (id=ISO numeric / name=alpha-2 / 全 249 件) で管理し CountryIsoCodeRepository 経由で解決する (ハードコードしない)。mtb_* の固定スキーマ (id/name/sort_no/discriminator_type) に準拠し、既存 mtb_country は改変しない。
  • UCP 署名は RFC 9421 / EC P-256 JWK (phpseclib3)。AgentCommerceMessageSignerInterface をアルゴリズム非依存にし、ACP の HMAC は後続で差し替え可能。

実装に関する補足(Appendix)

追加クラス (src/Eccube/Service/AgentCommerce/):

クラス 役割
MinorUnitConverter 通貨 minor unit ⇔ decimal 変換 (bcmath / ゼロデシマル / 負数)
AddressMappingService 住所 DTO マッピング / 国コード numeric→alpha-2 (マスタ mtb_country_iso_codeCountryIsoCodeRepository 経由で解決) / Pref→region
Entity/Master/CountryIsoCode + Repository/Master/CountryIsoCodeRepository ISO 3166-1 numeric→alpha-2 の新規マスタ (id=numeric / name=alpha-2 / discriminator=countryisocode)
Security/AgentCommerceScopeRegistry <protocol>:<capability> scope の妥当性・protocol 照合
Security/KeyStoreInterface + FilesystemKeyStore 鍵 PEM の保管 (env→既定ファイル)
Security/AgentCommerceMessageSignerInterface + UcpMessageSigner RFC 9421 EC P-256/ES256 署名・公開鍵 JWK・鍵ローテーション grace

本体・設定:

  • BaseInfo にフラグ 3 (acp_checkout_enabled / ucp_checkout_enabled / ucp_catalog_requires_authいずれも default false) を追加。dtb_base_info.csv ヘッダ追記、services.yaml に alias / bind。
    • 方針 (2026-06-09 整理): *_checkout_enabledcheckout の有無のみを制御する (checkout は日本未提供のため既定 OFF)。discovery / catalog は公開して害がないため常時公開とし、フラグでゲートしない。ACP feed push は認証情報 (base URL + API key) の有無で実質ガードされるため専用フラグは持たない (旧 acp_enabledacp_checkout_enabled / ucp_enableducp_checkout_enabled に改名、acp_feed_enabled / ucp_catalog_api_enabled は削除)。ucp_catalog_requires_auth は catalog の OAuth 必須モード用に維持 (api4 着手時に実装)。
    • 店舗設定 (/admin/setting/shop) にトグルを追加: ShopMasterTypeacp_checkout_enabled / ucp_checkout_enabled の有効化スイッチ (日本未提供の注記つき)。
    • カラム追加に ALTER TABLE マイグレーションは書かない (EC-CUBE 慣例: doctrine:schema:update で反映、前例 PR Googleアナリティクス機能を追加 #4912)。
    • google_pay_merchant_id は追加しない — 決済はプラグイン化方針 (Stripe 同様) のため、Google Pay の merchant_id は決済ハンドラプラグインが UCP discovery の payment_handlers に寄与する。
  • 新規マスタ mtb_country_iso_code (Entity/Master/CountryIsoCode + Repository): テーブルは schema:update で生成、import_csv (definition.yml 登録) で新規投入、既存環境は INSERT データ migration (Version20260604120000、COUNT ガード付き) で backfill。

レビュー時の注意:

  • EC-CUBE エンティティの getter 戻り型に不整合があり (Shipping::getName01/getKana01(): string は値 null で TypeError、Customer?string)、AddressMappingService は TypeError を null 扱いで吸収しています。
  • phpseclib3 の EC 公開鍵は toString('JWK'){kty,crv,x,y} を取得しています。

テスト(Test)

tests/Eccube/Tests/Service/AgentCommerce/ に Layer 0 (仕様適合性) / Layer 1 (純ロジック) / Layer 2 (Doctrine) / Layer 5 (署名) を追加。

  • PHPUnit: 52 tests / 608 assertions / 0 失敗・0 エラー (incomplete 1 = 意図的 markTestIncompleteAddressMappingServiceTest はマスタ参照のため Layer 2 化)
  • PHPStan level 6 (paths: src): No errors
  • php-cs-fixer: 修正不要
  • ローカルは SQLite (4.4 既定 DB) で Layer 2 まで完走。PostgreSQL / MySQL 固有の migration 移植性は CI マトリクスで検証。

相談(Discussion)

マイナーバージョン互換性保持のための制限事項チェックリスト

  • 既存機能の仕様変更はありません (追加カラムは default false で OFF、サービスは新規追加のみ)
  • フックポイントの呼び出しタイミングの変更はありません
  • フックポイントのパラメータの削除・データ型の変更はありません
  • twigファイルに渡しているパラメータの削除・データ型の変更はありません
  • Serviceクラスの公開関数の、引数の削除・データ型の変更はありません (新規クラスのみ)
  • 入出力ファイル(CSVなど)のフォーマット変更はありません (dtb_base_info install fixture のヘッダに列を追記したのみ・既存列は不変)

レビュワー確認項目

  • 動作確認
  • コードレビュー
  • E2E/Unit テスト確認(テストの追加・変更が必要かどうか)
  • 互換性が保持されているか
  • セキュリティ上の問題がないか
    • 権限を超えた操作が可能にならないか
    • 不要なファイルアップロードがないか
    • 外部へ公開されるファイルや機能の追加ではないか
    • テンプレートでのエスケープ漏れがないか

Summary by CodeRabbit

  • New Features
    • Agent Commerce 関連機能追加:メッセージ署名/検証、鍵管理、スコープ管理、通貨単位変換、住所データ変換、国別ISOコードマスタ、管理画面のチェックアウト有効化トグルとローカライズ文言、初期データ投入を追加
  • Chores
    • 鍵保管用ディレクトリを無視対象化し、格納先へのアクセス制限を強化
  • Tests
    • 署名・鍵管理・スコープ・通貨変換・住所変換・設定フラグ等のユニット/統合テストを追加

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Agent Commerce 共通基盤を追加します:鍵ストアと署名器、国コードマスタとマイグレーション、住所マッピング、通貨 minor-unit 変換、OAuth スコープレジストリ、BaseInfo フラグ、管理画面項目と幅広いテスト群を導入します。

Changes

Agent Commerce Common Base

Layer / File(s) Summary
プロジェクト設定とディレクトリセットアップ
.gitignore, .htaccess, app/keystore/.htaccess, app/config/eccube/services.yaml, app/config/eccube/services_test.yaml
/app/keystore/ を git 除外しつつ .gitkeep.htaccess を例外化。Apache の FilesMatch に key を追加し keystore ディレクトリを deny。DI に FilesystemKeyStore を定義、KeyStoreInterface と AgentCommerceMessageSignerInterface のエイリアスを追加。テスト用に AddressMappingService を public 化。
データモデル:Country ISO マスタとマイグレーション
app/DoctrineMigrations/Version20260604120000.php, src/Eccube/Entity/Master/CountryIsoCode.php, src/Eccube/Repository/Master/CountryIsoCodeRepository.php, src/Eccube/Resource/doctrine/import_csv/en/definition.yml, src/Eccube/Resource/doctrine/import_csv/ja/definition.yml
CountryIsoCode エンティティ/リポジトリと mtb_country_iso_code 用マイグレーションを追加(既存データがある場合は挿入スキップ)。CSV インポート定義を追加。
サービス層:住所マッピング
src/Eccube/Service/AgentCommerce/AddressMappingService.php, tests/.../AddressMappingServiceTest.php, app/config/eccube/services_test.yaml
Customer/CustomerAddress/Shipping を ACP/UCP 仕様の住所配列へ変換する AddressMappingService を追加。country numeric→alpha-2 変換で CountryIsoCodeRepository を使用。関連テストを追加。
サービス層:通貨変換
src/Eccube/Service/AgentCommerce/MinorUnitConverter.php, tests/.../MinorUnitConverterTest.php
MinorUnitConverter を追加し、major ⇄ minor 単位変換(bcmath、round-half-up、負数対応)と通貨桁数解決を実装。往復性・丸め・不正入力をテスト。
セキュリティ基盤:キーストア
src/Eccube/Service/AgentCommerce/Security/KeyStoreInterface.php, src/Eccube/Service/AgentCommerce/Security/FilesystemKeyStore.php
鍵の read/write を抽象化する KeyStoreInterface と、ファイルシステム上で PEM 鍵を永続化する FilesystemKeyStore を追加。パス上書き、ディレクトリ/ファイル権限を扱う。
セキュリティ実装:メッセージ署名(UCP)
src/Eccube/Service/AgentCommerce/Security/AgentCommerceMessageSignerInterface.php, src/Eccube/Service/AgentCommerce/Security/UcpMessageSigner.php, tests/.../UcpMessageSignerTest.php
AgentCommerceMessageSignerInterface を追加し、UcpMessageSigner を実装。EC P-256 (ES256) で署名・検証、公開 JWK 生成、RFC 7638 thumbprint による kid、鍵生成/永続化、grace 鍵検証を実装。テストで署名/検証、JWK 非公開性、鍵回転を検証。
セキュリティ実装:OAuth スコープレジストリ
src/Eccube/Service/AgentCommerce/Security/AgentCommerceScopeRegistry.php, tests/.../AgentCommerceScopeRegistryTest.php
canonical な protocol:capability スコープ集合を保持し、isValidScope()/scopesForProtocol()/supports() を提供。受理/拒否ケースを網羅するテストを追加。
管理画面:BaseInfo フラグと UI 表示
src/Eccube/Entity/BaseInfo.php, src/Eccube/Form/Type/Admin/ShopMasterType.php, src/Eccube/Resource/template/admin/Setting/Shop/shop_master.twig, src/Eccube/Resource/locale/messages.*.yaml, tests/.../BaseInfoAgentCommerceFlagsTest.php
BaseInfo に acp/ucp 関連 boolean カラムとアクセサを追加。管理画面フォームにトグルを追加し、文言を多言語で追加。デフォルト false を検証するテストを追加。
適合テスト:共通ベースの必須項目検証
tests/Eccube/Tests/Service/AgentCommerce/Conformance/AgentCommerceBaseConformanceTest.php
MinorUnitConverter と UcpMessageSigner の公開 JWK に関する conformance レベルのテストを追加(2-tier error の検証はコントローラ層に委ねるため未完扱い)。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

🐰 鍵は土の下、安心して眠るよ
住所は二文字でぴょんと揃えるよ
小数は跳ねて整数になるよ、ぴょんぴょん
署名は公開のみ、秘密は胸の中に💼
新しい基盤でみんなで跳ねよう!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed プルリクエストのタイトルは「feat(agent-commerce): エージェントコマース共通基盤 Phase 1a」であり、変更セット全体の主要な目的(エージェントコマース共通基盤の Phase 1a 実装)を正確に要約しており、ファイル一覧などのノイズなく簡潔かつ明確である。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread src/Eccube/Service/AgentCommerce/AddressMappingService.php Outdated
Comment thread src/Eccube/Service/AgentCommerce/AddressMappingService.php
nanasess added a commit to nanasess/ec-cube that referenced this pull request Jun 4, 2026
CI の rector ジョブ (PR EC-CUBE#6802) で検出された 8 ファイルの指摘を vendor/bin/rector で適用。
- AddressMappingService: 冗長な (int) キャストと三項を null 合体演算子に簡約
- UcpMessageSigner: コンストラクタプロパティ昇格
- テスト各種: self:: → $this->、final class 化、strict_types 宣言等

AgentCommerce テスト 53 件すべて成功を確認。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nanasess and others added 5 commits June 4, 2026 16:07
ACP/UCP 対応の共通基盤のうち CheckoutSession 非依存の先行スライスを実装。
トラック A (Product Feed / Discovery) を解放する最小集合。

- MinorUnitConverter: 通貨 minor unit 変換 (bcmath / ゼロデシマル / 負数)
- AddressMappingService: 住所マッピング・国コード numeric→alpha-2 (全249件網羅)
- AgentCommerceScopeRegistry: <protocol>:<capability> scope 照合
- KeyStoreInterface / FilesystemKeyStore: 鍵保管 (env パス上書き→既定ファイル、EC-CUBE#6797 雛形)
- AgentCommerceMessageSignerInterface / UcpMessageSigner: RFC 9421 EC P-256 / JWK 公開鍵 / 鍵ローテーション grace
- BaseInfo にフラグ5 (acp/ucp 有効化等、default false) + google_pay_merchant_id + migration
- 秘密鍵は dtb_baseinfo でなく app/keystore/ に保管 (EC-CUBE#6797、.htaccess/.gitignore 多重防御)

プライバシー/利用規約 URL はカラム化せず標準ページ (help_privacy/help_agreement) から自動生成する方針。
検証: PHPUnit 53 tests / 611 assertions / 0 失敗、PHPStan level6 No errors、php-cs-fixer 0件。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
minor-unit は通貨の小数桁数だけ桁が増える (一律 ×100 ではない) ことが
一目で分かるよう、docblock の例を JPY (×1) / USD (×100) の 2 桁までに統一。
3 桁通貨 (BHD 等) の 4 桁例は紛らわしいため削除。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ACP/UCP 用の 6 カラムは BaseInfo エンティティに #[ORM\Column] で定義済みのため、
公式アップデート手順 (doctrine:schema:update --force) で自動反映される。
カラム追加に ALTER TABLE マイグレーションを書かないのが EC-CUBE の慣例
(前例 PR EC-CUBE#4912: カラム追加に ALTER マイグレーション無し、INSERT のみ)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI の rector ジョブ (PR EC-CUBE#6802) で検出された 8 ファイルの指摘を vendor/bin/rector で適用。
- AddressMappingService: 冗長な (int) キャストと三項を null 合体演算子に簡約
- UcpMessageSigner: コンストラクタプロパティ昇格
- テスト各種: self:: → $this->、final class 化、strict_types 宣言等

AgentCommerce テスト 53 件すべて成功を確認。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
決済はプラグイン化方針 (Stripe 同様) のため、Google Pay の merchant_id は
core BaseInfo に持たせない。UCP discovery の payment_handlers は決済ハンドラ
プラグインが寄与する設計とする。あわせて rector 適用後の php-cs-fixer 整形
(ライセンスヘッダ直後の空行) をテストへ反映。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AddressMappingService の numeric->alpha-2 ハードコード const (249件) を廃止し、
新規マスタ mtb_country_iso_code で管理する。PR EC-CUBE#6802 レビュー指摘 (マスタテーブル化) に対応。

- 新規マスタ CountryIsoCode / CountryIsoCodeRepository を追加
- mtb_* の固定スキーマ (id/name/sort_no/discriminator_type) に準拠し、id=ISO numeric / name=alpha-2 を格納 (discriminator=countryisocode)
- 新規インストールは import_csv (definition.yml 登録)、既存環境は INSERT データ migration で backfill (mtb_country は改変しない)
- AddressMappingService はリポジトリ経由解決へ変更、テストを Layer 2 化

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI rector ジョブ (ContainerGetNameToTypeInTestsRector / AssertFuncCallToPHPUnitAssertRector)
の指摘に対応。get('doctrine') + ManagerRegistry 手動構築をやめ、services_test.yaml で
AddressMappingService を public 化しコンテナから FQCN 取得する方式へ変更。

- services_test.yaml: AddressMappingService を public 化 (consumer 未実装で private では除去されるため)
- AddressMappingServiceTest: self::getContainer()->get(AddressMappingService::class) に簡素化

検証: PHPUnit 52/608、PHPStan level6 No errors、php-cs-fixer 0、rector dry-run クリーン。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.31959% with 44 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.88%. Comparing base (3f76a03) to head (192db99).
⚠️ Report is 97 commits behind head on 4.4.

Files with missing lines Patch % Lines
...vice/AgentCommerce/Security/FilesystemKeyStore.php 0.00% 20 Missing ⚠️
...ervice/AgentCommerce/Security/UcpMessageSigner.php 86.20% 12 Missing ⚠️
src/Eccube/Entity/BaseInfo.php 33.33% 6 Missing ⚠️
...be/Service/AgentCommerce/AddressMappingService.php 90.32% 3 Missing ⚠️
...ccube/Service/AgentCommerce/MinorUnitConverter.php 92.00% 2 Missing ⚠️
...ntCommerce/Security/AgentCommerceScopeRegistry.php 94.44% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##                4.4    #6802      +/-   ##
============================================
- Coverage     75.10%   74.88%   -0.22%     
============================================
  Files           483      469      -14     
  Lines         26279    24223    -2056     
============================================
- Hits          19736    18140    -1596     
+ Misses         6543     6083     -460     
Flag Coverage Δ
Unit 74.88% <77.31%> (-0.22%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@nanasess nanasess marked this pull request as ready for review June 8, 2026 02:24
@nanasess

nanasess commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
src/Eccube/Service/AgentCommerce/Security/FilesystemKeyStore.php (1)

73-82: 💤 Low value

purpose パラメータのバリデーションを検討してください。

purpose がパス構築に直接使用されているため、../ 等を含む値が渡された場合、意図しないディレクトリへの書き込みが可能です。現在の DI 設定では purpose は固定値ですが、防御的プログラミングとしてバリデーションを追加することを推奨します。

🛡️ バリデーション追加の提案
 private function resolvePath(string $purpose): string
 {
+    if (!preg_match('/^[a-zA-Z0-9_-]+$/', $purpose)) {
+        throw new \InvalidArgumentException(sprintf('無効な purpose 識別子: "%s"', $purpose));
+    }
+
     $override = $this->envPathOverrides[$purpose] ?? '';

     if ($override !== '') {
         return $override;
     }

     return $this->projectDir.'/app/keystore/agent-commerce/'.$purpose.'.key';
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Eccube/Service/AgentCommerce/Security/FilesystemKeyStore.php` around
lines 73 - 82,
resolvePath関数で渡されるpurposeがそのままファイルパスに使われており、"../"等のパス操作を含むと任意のディレクトリに書き込めてしまうので、目的(purpose)の検証を追加してください:
resolvePath内で purpose が事前定義された許可リスト(例: 固定キー名配列)に含まれるか、もしくは正規表現でパス区切りや上位参照(".."
または "/" や "\" )を含まないことをチェックし、無効な場合は例外を投げるか空の override を返すようにし、envPathOverrides と
projectDir を使って組み立てる処理はその検証後にのみ実行するように変更してください。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/DoctrineMigrations/Version20260604120000.php`:
- Around line 48-55: down() currently deletes all rows from mtb_country_iso_code
even when up() is a no-op; change it to be explicitly irreversible instead of
deleting data: update the down() method in Version20260604120000 to throw an
IrreversibleMigrationException (e.g.
\Doctrine\Migrations\IrreversibleMigrationException) with a clear message
referencing self::NAME/mtb_country_iso_code, instead of calling
$this->addSql('DELETE FROM mtb_country_iso_code'); this makes the migration
abort on rollback and prevents unintended data loss.
- Around line 39-43: The current migration in Version20260604120000 uses a
simple presence check ($this->connection->fetchOne('SELECT COUNT(*) FROM
'.self::NAME) and if ($count > 0) return;) which skips backfill entirely when
any row exists; change this to verify against the expected dataset and only
insert missing rows: compute the expected key set (or expected total count) for
self::NAME, query existing keys/rows from self::NAME, determine which specific
entries are missing, and perform inserts only for those missing entries so
partial failures can be repaired rather than skipping the whole backfill.

In `@src/Eccube/Service/AgentCommerce/MinorUnitConverter.php`:
- Around line 57-68: The toMinorUnits method accepts $amount strings but only
guards '' and '.'; before any BCMath calls (bcmul/bcadd) add a strict format
validation for $amount (in MinorUnitConverter::toMinorUnits) using a regex that
allows an optional sign, digits, optional single decimal point with digits (e.g.
/^[+-]?\d+(\.\d+)?$/), rejecting commas or multiple dots; if the check fails
return 0, otherwise proceed with existing scale/factor, $scaled and bcmath
operations so malformed inputs like 'abc', '1,000', or '1..2' never reach
bcmul/bcadd.

In `@src/Eccube/Service/AgentCommerce/Security/FilesystemKeyStore.php`:
- Around line 54-65: The write() method currently ignores failures from mkdir(),
file_put_contents(), and chmod(), so update FilesystemKeyStore::write to detect
errors and throw exceptions: after calling resolvePath($purpose) and computing
$dir, check mkdir($dir, 0700, true) return (when directory didn't exist) and
throw a RuntimeException (or a domain-specific exception) on failure; check
file_put_contents($path, $pem) result (=== false) and throw if it failed; also
check chmod($path, 0600) return and throw if it fails. Keep using the existing
method names resolvePath and write, include clear error messages that include
$path or $dir for debugging, and ensure no silent failure paths remain.

In `@tests/Eccube/Tests/Service/AgentCommerce/AddressMappingServiceTest.php`:
- Around line 172-174: After calling fopen($csvPath, 'r') in
AddressMappingServiceTest, validate that $handle is not false before calling
fgetcsv; if fopen failed, fail the test or throw a clear exception (e.g. use
$this->fail(...) or throw new \RuntimeException(...)) with the $csvPath included
in the message so the failure is diagnosable, then proceed to fgetcsv($handle,
...) when the handle is valid.

In `@tests/Eccube/Tests/Service/AgentCommerce/BaseInfoAgentCommerceFlagsTest.php`:
- Around line 62-68: The current readBooleanFlag casts the getter result to
(bool) which hides nulls; instead call the getter on BaseInfo (using the same
dynamically-built names 'is'.$studly and 'get'.$studly), then check the raw
return value with is_bool(), return it if true, and if the getter returns null
or any non-bool throw a clear exception (or fail the test) indicating the
contract violation so nulls are not treated as false.

---

Nitpick comments:
In `@src/Eccube/Service/AgentCommerce/Security/FilesystemKeyStore.php`:
- Around line 73-82:
resolvePath関数で渡されるpurposeがそのままファイルパスに使われており、"../"等のパス操作を含むと任意のディレクトリに書き込めてしまうので、目的(purpose)の検証を追加してください:
resolvePath内で purpose が事前定義された許可リスト(例: 固定キー名配列)に含まれるか、もしくは正規表現でパス区切りや上位参照(".."
または "/" や "\" )を含まないことをチェックし、無効な場合は例外を投げるか空の override を返すようにし、envPathOverrides と
projectDir を使って組み立てる処理はその検証後にのみ実行するように変更してください。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bbe18c12-17ac-40c7-be75-fe7fc5b9190e

📥 Commits

Reviewing files that changed from the base of the PR and between 9820448 and cbd91b0.

⛔ Files ignored due to path filters (4)
  • src/Eccube/Resource/doctrine/import_csv/en/dtb_base_info.csv is excluded by !**/*.csv
  • src/Eccube/Resource/doctrine/import_csv/en/mtb_country_iso_code.csv is excluded by !**/*.csv
  • src/Eccube/Resource/doctrine/import_csv/ja/dtb_base_info.csv is excluded by !**/*.csv
  • src/Eccube/Resource/doctrine/import_csv/ja/mtb_country_iso_code.csv is excluded by !**/*.csv
📒 Files selected for processing (25)
  • .gitignore
  • .htaccess
  • app/DoctrineMigrations/Version20260604120000.php
  • app/config/eccube/services.yaml
  • app/config/eccube/services_test.yaml
  • app/keystore/.gitkeep
  • app/keystore/.htaccess
  • src/Eccube/Entity/BaseInfo.php
  • src/Eccube/Entity/Master/CountryIsoCode.php
  • src/Eccube/Repository/Master/CountryIsoCodeRepository.php
  • src/Eccube/Resource/doctrine/import_csv/en/definition.yml
  • src/Eccube/Resource/doctrine/import_csv/ja/definition.yml
  • src/Eccube/Service/AgentCommerce/AddressMappingService.php
  • src/Eccube/Service/AgentCommerce/MinorUnitConverter.php
  • src/Eccube/Service/AgentCommerce/Security/AgentCommerceMessageSignerInterface.php
  • src/Eccube/Service/AgentCommerce/Security/AgentCommerceScopeRegistry.php
  • src/Eccube/Service/AgentCommerce/Security/FilesystemKeyStore.php
  • src/Eccube/Service/AgentCommerce/Security/KeyStoreInterface.php
  • src/Eccube/Service/AgentCommerce/Security/UcpMessageSigner.php
  • tests/Eccube/Tests/Service/AgentCommerce/AddressMappingServiceTest.php
  • tests/Eccube/Tests/Service/AgentCommerce/BaseInfoAgentCommerceFlagsTest.php
  • tests/Eccube/Tests/Service/AgentCommerce/Conformance/AgentCommerceBaseConformanceTest.php
  • tests/Eccube/Tests/Service/AgentCommerce/MinorUnitConverterTest.php
  • tests/Eccube/Tests/Service/AgentCommerce/Security/AgentCommerceScopeRegistryTest.php
  • tests/Eccube/Tests/Service/AgentCommerce/Security/UcpMessageSignerTest.php

Comment thread app/DoctrineMigrations/Version20260604120000.php
Comment thread app/DoctrineMigrations/Version20260604120000.php
Comment thread src/Eccube/Service/AgentCommerce/MinorUnitConverter.php Outdated
Comment thread src/Eccube/Service/AgentCommerce/Security/FilesystemKeyStore.php
nanasess added a commit to nanasess/ec-cube that referenced this pull request Jun 8, 2026
…トラックA)

エージェントコマース共通基盤 Phase 1a (EC-CUBE#6802) の上に、CheckoutSession 非依存の
トラック A (Product Feed / Catalog / Discovery) を 1 PR で実装する。

- Foundation: protocol 非依存 DTO (AgentCatalogItemDto 等) / ProductReferenceResolver
  (sku/product_class_id/barcode→ProductClass、barcode は Customize seam) / CatalogProvider
  (toIterable でメモリ蓄積回避) / CatalogMapper (表示商品のみ・price02→minor unit・availability)
- ACP Feed: products.jsonl/metadata.json 生成 + pre-push スキーマ検証 (justinrainbow/json-schema)
  + push クライアント (AcpFeedClientInterface、outbound Bearer、Error shape 変換、多段ガード)。
  実機送出は acp_feed_enabled + 設定有無でガード、Bearer は #[SensitiveParameter]
- UCP Catalog: POST /catalog/{search,lookup,product} (v2026-04-08 の RPC 形式・GET ではない)。
  UcpCatalogResponseBuilder (ucp wrapper) / FilesystemAdapter+Lock キャッシュ (stampede 防止)
  / gzip。無効時 404。認証必須モード・GraphQL は api4 未導入のため TODO。
  lookup の variants[].inputs (input_correlation) は未実装 (schema 契約テストで incomplete 追跡)
- Discovery: GET /.well-known/ucp。UcpProfileBuilder (signing_keys=getPublicJwks 公開鍵のみ・
  capability 宣言・endpoint は RequestContext 動的生成)、Cache-Control public max-age=300。
  payment_handlers はプラグイン寄与の tagged seam (既定空)
- 管理画面 + CLI の 2 系統を標準提供: eccube:acp-feed:push --full /
  eccube:ucp-catalog:cache:warmup / :clear、管理画面ボタン (CSRF 検証・検証目的限定の注記)
- キャッシュ無効化 EventListener (Product/ProductClass 更新→UCP キャッシュ clear)
- 依存追加: symfony/http-client (ACP push 用、first-party)。framework.lock: flock (外部インフラ不要)
- テスト: Layer 0 適合性 / Layer 1 マッピング / Layer 2 スキーマ契約・DB 突合 / Layer 3 Web
  / Layer 5 push。183 tests / 954 assertions / 0 failures (incomplete 7 は意図的)。
  spec schema はリポジトリに同梱しない (Apache-2.0 露出・case-collision 回避): ACP は
  src/Eccube/Resource/AgentCommerce/Acp/schema.feed.json の runtime リソースを再利用、
  UCP は CI で公式リポジトリから取得 (var/・gitignore) + ローカルは specifications/ フォールバック、
  無ければ skip。手順は tests/.../AgentCommerce/README.md / 出所明記は各 README

PHPStan level 6 No errors / php-cs-fixer 0 / rector clean。本 PR は eccube-api4 非依存。

Refs EC-CUBE#6794
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nanasess added a commit to nanasess/ec-cube that referenced this pull request Jun 9, 2026
…トラックA)

エージェントコマース共通基盤 Phase 1a (EC-CUBE#6802) の上に、CheckoutSession 非依存の
トラック A (Product Feed / Catalog / Discovery) を 1 PR で実装する。

- Foundation: protocol 非依存 DTO (AgentCatalogItemDto 等) / ProductReferenceResolver
  (sku/product_class_id/barcode→ProductClass、barcode は Customize seam) / CatalogProvider
  (toIterable でメモリ蓄積回避) / CatalogMapper (表示商品のみ・price02→minor unit・availability)
- ACP Feed: products.jsonl/metadata.json 生成 + pre-push スキーマ検証 (justinrainbow/json-schema)
  + push クライアント (AcpFeedClientInterface、outbound Bearer、Error shape 変換、多段ガード)。
  実機送出は acp_feed_enabled + 設定有無でガード、Bearer は #[SensitiveParameter]
- UCP Catalog: POST /catalog/{search,lookup,product} (v2026-04-08 の RPC 形式・GET ではない)。
  UcpCatalogResponseBuilder (ucp wrapper) / FilesystemAdapter+Lock キャッシュ (stampede 防止)
  / gzip。無効時 404。認証必須モード・GraphQL は api4 未導入のため TODO。
  lookup の variants[].inputs (input_correlation) は未実装 (schema 契約テストで incomplete 追跡)
- Discovery: GET /.well-known/ucp。UcpProfileBuilder (signing_keys=getPublicJwks 公開鍵のみ・
  capability 宣言・endpoint は RequestContext 動的生成)、Cache-Control public max-age=300。
  payment_handlers はプラグイン寄与の tagged seam (既定空)
- 管理画面 + CLI の 2 系統を標準提供: eccube:acp-feed:push --full /
  eccube:ucp-catalog:cache:warmup / :clear、管理画面ボタン (CSRF 検証・検証目的限定の注記)
- キャッシュ無効化 EventListener (Product/ProductClass 更新→UCP キャッシュ clear)
- 依存追加: symfony/http-client (ACP push 用、first-party)。framework.lock: flock (外部インフラ不要)
- テスト: Layer 0 適合性 / Layer 1 マッピング / Layer 2 スキーマ契約・DB 突合 / Layer 3 Web
  / Layer 5 push。183 tests / 954 assertions / 0 failures (incomplete 7 は意図的)。
  spec schema はリポジトリに同梱しない (Apache-2.0 露出・case-collision 回避): ACP は
  src/Eccube/Resource/AgentCommerce/Acp/schema.feed.json の runtime リソースを再利用、
  UCP は CI で公式リポジトリから取得 (var/・gitignore) + ローカルは specifications/ フォールバック、
  無ければ skip。手順は tests/.../AgentCommerce/README.md / 出所明記は各 README

PHPStan level 6 No errors / php-cs-fixer 0 / rector clean。本 PR は eccube-api4 非依存。

Refs EC-CUBE#6794
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nanasess added a commit to nanasess/ec-cube that referenced this pull request Jun 9, 2026
…トラックA)

エージェントコマース共通基盤 Phase 1a (EC-CUBE#6802) の上に、CheckoutSession 非依存の
トラック A (Product Feed / Catalog / Discovery) を 1 PR で実装する。

- Foundation: protocol 非依存 DTO (AgentCatalogItemDto 等) / ProductReferenceResolver
  (sku/product_class_id/barcode→ProductClass、barcode は Customize seam) / CatalogProvider
  (toIterable でメモリ蓄積回避) / CatalogMapper (表示商品のみ・price02→minor unit・availability)
- ACP Feed: products.jsonl/metadata.json 生成 + pre-push スキーマ検証 (justinrainbow/json-schema)
  + push クライアント (AcpFeedClientInterface、outbound Bearer、Error shape 変換、多段ガード)。
  実機送出は acp_feed_enabled + 設定有無でガード、Bearer は #[SensitiveParameter]
- UCP Catalog: POST /catalog/{search,lookup,product} (v2026-04-08 の RPC 形式・GET ではない)。
  UcpCatalogResponseBuilder (ucp wrapper) / FilesystemAdapter+Lock キャッシュ (stampede 防止)
  / gzip。無効時 404。認証必須モード・GraphQL は api4 未導入のため TODO。
  lookup の variants[].inputs (input_correlation) は未実装 (schema 契約テストで incomplete 追跡)
- Discovery: GET /.well-known/ucp。UcpProfileBuilder (signing_keys=getPublicJwks 公開鍵のみ・
  capability 宣言・endpoint は RequestContext 動的生成)、Cache-Control public max-age=300。
  payment_handlers はプラグイン寄与の tagged seam (既定空)
- 管理画面 + CLI の 2 系統を標準提供: eccube:acp-feed:push --full /
  eccube:ucp-catalog:cache:warmup / :clear、管理画面ボタン (CSRF 検証・検証目的限定の注記)
- キャッシュ無効化 EventListener (Product/ProductClass 更新→UCP キャッシュ clear)
- 依存追加: symfony/http-client (ACP push 用、first-party)。framework.lock: flock (外部インフラ不要)
- テスト: Layer 0 適合性 / Layer 1 マッピング / Layer 2 スキーマ契約・DB 突合 / Layer 3 Web
  / Layer 5 push。183 tests / 954 assertions / 0 failures (incomplete 7 は意図的)。
  spec schema はリポジトリに同梱しない (Apache-2.0 露出・case-collision 回避): ACP は
  src/Eccube/Resource/AgentCommerce/Acp/schema.feed.json の runtime リソースを再利用、
  UCP は CI で公式リポジトリから取得 (var/・gitignore) + ローカルは specifications/ フォールバック、
  無ければ skip。手順は tests/.../AgentCommerce/README.md / 出所明記は各 README

PHPStan level 6 No errors / php-cs-fixer 0 / rector clean。本 PR は eccube-api4 非依存。

Refs EC-CUBE#6794
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
BaseInfo の有効化フラグを「checkout の有無を制御する」意味へ整理する。
discovery / catalog は公開して害がないため常時公開とし (ゲート撤去は EC-CUBE#6794)、
ACP feed push は認証情報の有無で実質ガードされるためフラグ不要とする。

- 改名: acp_enabled → acp_checkout_enabled / ucp_enabled → ucp_checkout_enabled
  (getter は isAcpCheckoutEnabled / isUcpCheckoutEnabled)
- 削除: acp_feed_enabled (push は base URL + API key の有無でガード) /
  ucp_catalog_api_enabled (UCP Catalog は常時公開)
- 維持: ucp_catalog_requires_auth (catalog の OAuth 必須モードを api4 着手時に実装)
- dtb_base_info.csv (ja/en) ヘッダを 3 フラグへ更新
- 店舗設定 (ShopMasterType / @admin/Setting/Shop/shop_master.twig) に
  acp_checkout_enabled / ucp_checkout_enabled のトグルを追加 (checkout は日本未提供の注記つき)
- BaseInfoAgentCommerceFlagsTest を 3 フラグへ更新

PHPStan level 6 No errors / php-cs-fixer 0 / 関連テスト green。
カラム変更は schema:update 方式 (ALTER マイグレーションは書かない)。

Refs EC-CUBE#6777
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/Eccube/Tests/Service/AgentCommerce/BaseInfoAgentCommerceFlagsTest.php (1)

62-72: 💤 Low value

型キャストによる null 隠蔽の懸念は strict_types で軽減されています。

過去のレビューコメントで Line 67 の (bool) キャストが nullfalse に変換してしまう懸念が指摘されていますが、本ファイルは declare(strict_types=1); を宣言しており、かつエンティティの getter には戻り値型 bool が明示されているため、仮にプロパティが null であれば PHP が TypeError を投げます。そのため現在の実装でも実質的に安全です。

ただし、より明示的な型チェック($this->assertIsBool($value, ...))を追加することで、テストの意図がより明確になり、将来的な変更に対してもロバストになります。

♻️ より明示的な型チェック案(任意)
 private function readBooleanFlag(BaseInfo $BaseInfo, string $property): bool
 {
     $studly = str_replace('_', '', ucwords($property, '_'));
     foreach (['is'.$studly, 'get'.$studly] as $getter) {
         if (method_exists($BaseInfo, $getter)) {
-            return (bool) $BaseInfo->{$getter}();
+            $value = $BaseInfo->{$getter}();
+            $this->assertIsBool($value, sprintf('BaseInfo getter "%s" must return bool, got %s', $getter, get_debug_type($value)));
+            return $value;
         }
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Eccube/Tests/Service/AgentCommerce/BaseInfoAgentCommerceFlagsTest.php`
around lines 62 - 72, The readBooleanFlag helper currently casts the getter
result to (bool) which can mask null; update readBooleanFlag to call the
discovered getter (is{Studly} or get{Studly}) into a local $value, use
$this->assertIsBool($value, sprintf('Getter %s must return bool for flag "%s"',
$getter, $property)) to explicitly validate the type, then return $value;
reference the function name readBooleanFlag and the dynamic getters 'is'.$studly
and 'get'.$studly when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/Eccube/Tests/Service/AgentCommerce/BaseInfoAgentCommerceFlagsTest.php`:
- Around line 62-72: The readBooleanFlag helper currently casts the getter
result to (bool) which can mask null; update readBooleanFlag to call the
discovered getter (is{Studly} or get{Studly}) into a local $value, use
$this->assertIsBool($value, sprintf('Getter %s must return bool for flag "%s"',
$getter, $property)) to explicitly validate the type, then return $value;
reference the function name readBooleanFlag and the dynamic getters 'is'.$studly
and 'get'.$studly when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 683938ec-5be0-4856-90cf-8d42c31a408e

📥 Commits

Reviewing files that changed from the base of the PR and between cbd91b0 and 97f6853.

⛔ Files ignored due to path filters (2)
  • src/Eccube/Resource/doctrine/import_csv/en/dtb_base_info.csv is excluded by !**/*.csv
  • src/Eccube/Resource/doctrine/import_csv/ja/dtb_base_info.csv is excluded by !**/*.csv
📒 Files selected for processing (6)
  • src/Eccube/Entity/BaseInfo.php
  • src/Eccube/Form/Type/Admin/ShopMasterType.php
  • src/Eccube/Resource/locale/messages.en.yaml
  • src/Eccube/Resource/locale/messages.ja.yaml
  • src/Eccube/Resource/template/admin/Setting/Shop/shop_master.twig
  • tests/Eccube/Tests/Service/AgentCommerce/BaseInfoAgentCommerceFlagsTest.php
✅ Files skipped from review due to trivial changes (1)
  • src/Eccube/Resource/locale/messages.en.yaml

nanasess and others added 2 commits June 11, 2026 15:55
- MinorUnitConverter: 不正な金額文字列 (abc / 1,000 / 1..2 等) を
  BCMath 呼び出し前に正規表現で弾き、ValueError を防止 (仕様の「不正は 0」契約遵守)
- FilesystemKeyStore: 鍵書き込み時の mkdir / file_put_contents 失敗を
  RuntimeException で検知し、サイレント失敗を防止
- Version20260604120000: down() を不可逆 migration として明示し、
  新規インストール (up() が no-op) 環境での import_csv 由来データ巻き添え削除を回避
- AddressMappingServiceTest: fopen 後に assertIsResource を追加し診断性を向上
- MinorUnitConverterTest: 不正・空入力の回帰テスト 8 ケースを追加

CodeRabbit 指摘のうち COUNT(*) 判定と (bool) キャストの 2 件は非妥当のため非対応。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MinorUnitConverter::toMinorUnits の入力検証を、正規表現での形式チェックから
bcmul/bcadd の ValueError 捕捉へ変更する。

- BCMath が「受け付ける数値文字列形式」の唯一の権威であり、正規表現で再実装すると
  仕様の二重管理・他箇所への正規表現の拡散を招くため、判定を BCMath 自身へ委譲する
- 空文字 '' / '.' は BCMath が 0 として扱うため明示チェックも不要になり簡素化
- is_numeric は指数表記 (1e3) を true と判定するが BCMath では ValueError になり
  不適 (実証済み)。ValueError 捕捉なら指数表記・hex も正しく 0 に倒せる
- 回帰テストに指数表記 (1e3 / 1.5e3) と hex (0x1A) ケースを追加

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
FilesystemKeyStore::write が file_put_contents で umask 既定 (通常 0644) の
パーミッションでファイルを作成し、その後 chmod(0600) するため、その間だけ
秘密鍵が group/other から読める瞬間が生じていた。書き込みの間だけ
umask(0077) に切り替え、作成時点から 0600 になるようにする。あわせて
chmod の戻り値を検査し失敗時に例外を投げる。

CodeRabbit レビュー指摘 (PR EC-CUBE#6825 経由・本ファイルは EC-CUBE#6802 由来) 対応。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ー対応)

CodeRabbit レビュー指摘 (EC-CUBE#6777/EC-CUBE#6797 共通鍵保管) への対応。

- resolvePath の $purpose は既定パスへ直接連結されるため、"../" 等によるパストラバーサルを防ぐべく
  許可文字 ([a-z0-9_-]) のみに制限し、許可外は InvalidArgumentException を投げる
- FilesystemKeyStoreTest を追加 (不正 purpose の reject / 正常 purpose の受理)

検証: FilesystemKeyStoreTest 6 tests 0 失敗 / PHPStan level6 src No errors / php-cs-fixer 0

Refs EC-CUBE#6797

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nanasess added a commit to nanasess/ec-cube that referenced this pull request Jun 19, 2026
PR EC-CUBE#6843 のレビュー指摘のうち ACP 層所管の 6 件を修正:

- complete の decodeBody() を try 内へ移動。不正 JSON が 500 ではなく
  400 プロトコルエラーに変換され、create/update と一貫する
- findSession にセッション所有者 (agent_id) 照合を追加。他エージェントの
  セッションへの越境アクセスを存在秘匿で 404 拒否 (多層防御)
- line_items の id/quantity を正の整数のみ許可。非数値→0・負数の素通りを
  防ぎ、不正値は AgentCheckoutException → 400 に寄せる
- AcpMessageMapper の raw HTML 検知を包括化。任意タグ・HTML コメントを
  検知しつつ CommonMark の autolink は誤検知しない
- Discovery テストの max-age を固定値一致から >= 3600 の下限判定へ
- テスト Stub に declare(strict_types=1) を追加

越境遮断・不正値・不正 JSON・raw HTML 包括検知の回帰テストを追加。
B 群 (EC-CUBE#6825 checkout-core) / C 群 (EC-CUBE#6802 base) 所管の指摘は各 PR 側で対応。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI の rector で検出された 2 件を適用:
- YieldDataProviderRector: data provider を return [...] から yield + 戻り型 \Iterator へ
- AttributeArgumentsOrderRector: #[DataProvider('...')] を #[DataProvider(methodName: '...')] へ

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant