From 569154fcc6f2edd02cb38b60837b20b1b22b1f04 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Sat, 16 May 2026 10:40:55 +0900 Subject: [PATCH 1/4] Add be-framework/psalm-plugin to all demos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wires up the Be Framework Psalm plugin in each demo's composer.json and adds a per-demo psalm.xml so contributors can statically detect: - Being constructors missing #[Input] or #[Inject] - #[Validate] methods throwing non-DomainException (silently bypassed) Dogfood results highlight the plugin's value: 6 real bugs surfaced — blog-publishing (4) and user-registration (2) had #[Validate] methods throwing InvalidArgumentException, which the framework does not catch. Those throws would silently bypass validation at runtime. Stock unused-class / unused-method / unused-property false positives (Be Framework loads classes via #[Be] reflection) are suppressed in each psalm.xml. Run with: composer psalm --- demos/blog-publishing/composer.json | 3 ++ demos/blog-publishing/psalm.xml | 43 +++++++++++++++++++++++++++ demos/contact-form/composer.json | 3 ++ demos/contact-form/psalm.xml | 43 +++++++++++++++++++++++++++ demos/hello-world/composer.json | 3 ++ demos/hello-world/psalm.xml | 43 +++++++++++++++++++++++++++ demos/insurance-claim/composer.json | 3 ++ demos/insurance-claim/psalm.xml | 43 +++++++++++++++++++++++++++ demos/loan-application/composer.json | 3 ++ demos/loan-application/psalm.xml | 43 +++++++++++++++++++++++++++ demos/medical-triage/composer.json | 3 ++ demos/medical-triage/psalm.xml | 43 +++++++++++++++++++++++++++ demos/order-processing/composer.json | 3 ++ demos/order-processing/psalm.xml | 43 +++++++++++++++++++++++++++ demos/user-registration/composer.json | 3 ++ demos/user-registration/psalm.xml | 43 +++++++++++++++++++++++++++ 16 files changed, 368 insertions(+) create mode 100644 demos/blog-publishing/psalm.xml create mode 100644 demos/contact-form/psalm.xml create mode 100644 demos/hello-world/psalm.xml create mode 100644 demos/insurance-claim/psalm.xml create mode 100644 demos/loan-application/psalm.xml create mode 100644 demos/medical-triage/psalm.xml create mode 100644 demos/order-processing/psalm.xml create mode 100644 demos/user-registration/psalm.xml diff --git a/demos/blog-publishing/composer.json b/demos/blog-publishing/composer.json index 8d1f927..ba9b5e5 100644 --- a/demos/blog-publishing/composer.json +++ b/demos/blog-publishing/composer.json @@ -18,13 +18,16 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/blog-publishing/psalm.xml b/demos/blog-publishing/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/blog-publishing/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/contact-form/composer.json b/demos/contact-form/composer.json index ece0256..a9aa8f0 100644 --- a/demos/contact-form/composer.json +++ b/demos/contact-form/composer.json @@ -18,13 +18,16 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/contact-form/psalm.xml b/demos/contact-form/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/contact-form/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/hello-world/composer.json b/demos/hello-world/composer.json index 795c46a..71d5ffa 100644 --- a/demos/hello-world/composer.json +++ b/demos/hello-world/composer.json @@ -18,17 +18,20 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { "dev": "php bin/be.php 'hello?name=World'", "profile": "XDEBUG_MODE=trace php -d xdebug.use_compression=0 -d extension=xhprof.so bin/be.php 'hello?name=World'", + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { "dev": "Run the Hello World demo in dev mode; writes a semantic log to var/log/*.json without Xdebug/XHProf profiling.", "profile": "Run the Hello World demo with semantic profiling; writes a semantic log to var/log/*.json with uncompressed Xdebug trace and xhprof enabled.", + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/hello-world/psalm.xml b/demos/hello-world/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/hello-world/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/insurance-claim/composer.json b/demos/insurance-claim/composer.json index a629a17..7b1e4ef 100644 --- a/demos/insurance-claim/composer.json +++ b/demos/insurance-claim/composer.json @@ -17,13 +17,16 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/insurance-claim/psalm.xml b/demos/insurance-claim/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/insurance-claim/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/loan-application/composer.json b/demos/loan-application/composer.json index 920056a..c59475b 100644 --- a/demos/loan-application/composer.json +++ b/demos/loan-application/composer.json @@ -17,13 +17,16 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/loan-application/psalm.xml b/demos/loan-application/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/loan-application/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/medical-triage/composer.json b/demos/medical-triage/composer.json index 76028f6..3781ab1 100644 --- a/demos/medical-triage/composer.json +++ b/demos/medical-triage/composer.json @@ -17,17 +17,20 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { "dev": "php bin/be.php", "profile": "XDEBUG_MODE=trace php -d xdebug.use_compression=0 -d extension=xhprof.so bin/be.php", + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { "dev": "Run the Medical Triage demo in dev mode; writes a semantic log to var/log/*.json without Xdebug/XHProf profiling.", "profile": "Run the Medical Triage demo with semantic profiling; writes a semantic log to var/log/*.json with uncompressed Xdebug trace and xhprof enabled.", + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/medical-triage/psalm.xml b/demos/medical-triage/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/medical-triage/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/order-processing/composer.json b/demos/order-processing/composer.json index 47fa0a9..41ed17c 100644 --- a/demos/order-processing/composer.json +++ b/demos/order-processing/composer.json @@ -17,17 +17,20 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { "dev": "php bin/be.php", "profile": "XDEBUG_MODE=trace php -d xdebug.use_compression=0 -d extension=xhprof.so bin/be.php", + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { "dev": "Run the Order Processing demo in dev mode; writes a semantic log to var/log/*.json without Xdebug/XHProf profiling.", "profile": "Run the Order Processing demo with semantic profiling; writes a semantic log to var/log/*.json with uncompressed Xdebug trace and xhprof enabled.", + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/order-processing/psalm.xml b/demos/order-processing/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/order-processing/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demos/user-registration/composer.json b/demos/user-registration/composer.json index 0b77b6b..206ac45 100644 --- a/demos/user-registration/composer.json +++ b/demos/user-registration/composer.json @@ -19,17 +19,20 @@ "ray/di": "^2.18" }, "require-dev": { + "be-framework/psalm-plugin": "dev-main", "phpunit/phpunit": "^12" }, "scripts": { "dev": "php bin/be.php", "profile": "XDEBUG_MODE=trace php -d xdebug.use_compression=0 -d extension=xhprof.so bin/be.php", + "psalm": "psalm --show-info=false", "stree": "vendor/bin/stree $(ls -t var/log/*.json | head -1)", "stree:full": "vendor/bin/stree --full $(ls -t var/log/*.json | head -1)" }, "scripts-descriptions": { "dev": "Run the User Registration demo in dev mode; writes a semantic log to var/log/*.json without Xdebug/XHProf profiling.", "profile": "Run the User Registration demo with semantic profiling; writes a semantic log to var/log/*.json with uncompressed Xdebug trace and xhprof enabled.", + "psalm": "Run static analysis with Psalm + Be Framework plugin.", "stree": "Render the latest var/log/*.json as a compact tree.", "stree:full": "Render the latest var/log/*.json as a semantic full tree with full props and close.profile details." } diff --git a/demos/user-registration/psalm.xml b/demos/user-registration/psalm.xml new file mode 100644 index 0000000..76620e9 --- /dev/null +++ b/demos/user-registration/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 23ce1766c43316ae7aa1c718aa5e1173afbc5970 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Sat, 16 May 2026 17:09:18 +0900 Subject: [PATCH 2/4] Fix #[Validate] throws that bypass framework validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six validators were throwing InvalidArgumentException from inside #[Validate] methods. The framework's SemanticValidator only catches DomainException, so those throws would silently bypass validation at runtime — the offending value would reach business logic unchecked. Detected by be-framework/psalm-plugin (InvalidValidateException rule). - blog-publishing: AuthorName, Excerpt, HtmlBody, Slug now throw new InvalidAuthorNameException / InvalidExcerptException / InvalidHtmlBodyException / InvalidSlugException - user-registration: AvatarUrl, HashedPassword now throw new InvalidAvatarUrlException / InvalidHashedPasswordException Each new exception extends \DomainException and carries a #[Message] attribute matching the existing convention in src/Exception/. --- .../src/Exception/InvalidAuthorNameException.php | 16 ++++++++++++++++ .../src/Exception/InvalidExcerptException.php | 16 ++++++++++++++++ .../src/Exception/InvalidHtmlBodyException.php | 16 ++++++++++++++++ .../src/Exception/InvalidSlugException.php | 16 ++++++++++++++++ .../blog-publishing/src/Semantic/AuthorName.php | 4 ++-- demos/blog-publishing/src/Semantic/Excerpt.php | 4 ++-- demos/blog-publishing/src/Semantic/HtmlBody.php | 4 ++-- demos/blog-publishing/src/Semantic/Slug.php | 4 ++-- .../src/Exception/InvalidAvatarUrlException.php | 16 ++++++++++++++++ .../Exception/InvalidHashedPasswordException.php | 16 ++++++++++++++++ .../user-registration/src/Semantic/AvatarUrl.php | 4 ++-- .../src/Semantic/HashedPassword.php | 4 ++-- 12 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 demos/blog-publishing/src/Exception/InvalidAuthorNameException.php create mode 100644 demos/blog-publishing/src/Exception/InvalidExcerptException.php create mode 100644 demos/blog-publishing/src/Exception/InvalidHtmlBodyException.php create mode 100644 demos/blog-publishing/src/Exception/InvalidSlugException.php create mode 100644 demos/user-registration/src/Exception/InvalidAvatarUrlException.php create mode 100644 demos/user-registration/src/Exception/InvalidHashedPasswordException.php diff --git a/demos/blog-publishing/src/Exception/InvalidAuthorNameException.php b/demos/blog-publishing/src/Exception/InvalidAuthorNameException.php new file mode 100644 index 0000000..09e4601 --- /dev/null +++ b/demos/blog-publishing/src/Exception/InvalidAuthorNameException.php @@ -0,0 +1,16 @@ + 'Author name cannot be empty.', + 'ja' => '著者名は空にできません。' +])] +final class InvalidAuthorNameException extends DomainException +{ +} diff --git a/demos/blog-publishing/src/Exception/InvalidExcerptException.php b/demos/blog-publishing/src/Exception/InvalidExcerptException.php new file mode 100644 index 0000000..c1d444d --- /dev/null +++ b/demos/blog-publishing/src/Exception/InvalidExcerptException.php @@ -0,0 +1,16 @@ + 'Excerpt is too long. Must be 250 characters or fewer.', + 'ja' => '抜粋が長すぎます。250文字以下で入力してください。' +])] +final class InvalidExcerptException extends DomainException +{ +} diff --git a/demos/blog-publishing/src/Exception/InvalidHtmlBodyException.php b/demos/blog-publishing/src/Exception/InvalidHtmlBodyException.php new file mode 100644 index 0000000..ff31179 --- /dev/null +++ b/demos/blog-publishing/src/Exception/InvalidHtmlBodyException.php @@ -0,0 +1,16 @@ + 'HTML body cannot be empty.', + 'ja' => 'HTML本文は空にできません。' +])] +final class InvalidHtmlBodyException extends DomainException +{ +} diff --git a/demos/blog-publishing/src/Exception/InvalidSlugException.php b/demos/blog-publishing/src/Exception/InvalidSlugException.php new file mode 100644 index 0000000..db34fa0 --- /dev/null +++ b/demos/blog-publishing/src/Exception/InvalidSlugException.php @@ -0,0 +1,16 @@ + 'Invalid slug format. Use lowercase letters, digits, and hyphens only.', + 'ja' => 'スラッグの形式が不正です。小文字・数字・ハイフンのみ使用できます。' +])] +final class InvalidSlugException extends DomainException +{ +} diff --git a/demos/blog-publishing/src/Semantic/AuthorName.php b/demos/blog-publishing/src/Semantic/AuthorName.php index f03964c..5d8a52b 100644 --- a/demos/blog-publishing/src/Semantic/AuthorName.php +++ b/demos/blog-publishing/src/Semantic/AuthorName.php @@ -5,7 +5,7 @@ namespace Be\Pattern\BlogPublishing\Semantic; use Be\Framework\Attribute\Validate; -use InvalidArgumentException; +use Be\Pattern\BlogPublishing\Exception\InvalidAuthorNameException; /** * AuthorName - Semantic validation @@ -20,7 +20,7 @@ final class AuthorName public function validate(string $authorName): void { if (empty(trim($authorName))) { - throw new InvalidArgumentException('Author name cannot be empty'); + throw new InvalidAuthorNameException(); } } } diff --git a/demos/blog-publishing/src/Semantic/Excerpt.php b/demos/blog-publishing/src/Semantic/Excerpt.php index a28992e..125b05e 100644 --- a/demos/blog-publishing/src/Semantic/Excerpt.php +++ b/demos/blog-publishing/src/Semantic/Excerpt.php @@ -5,7 +5,7 @@ namespace Be\Pattern\BlogPublishing\Semantic; use Be\Framework\Attribute\Validate; -use InvalidArgumentException; +use Be\Pattern\BlogPublishing\Exception\InvalidExcerptException; /** * Excerpt - Semantic validation @@ -18,7 +18,7 @@ final class Excerpt public function validate(string $excerpt): void { if (mb_strlen($excerpt) > 250) { - throw new InvalidArgumentException('Excerpt too long'); + throw new InvalidExcerptException(); } } } diff --git a/demos/blog-publishing/src/Semantic/HtmlBody.php b/demos/blog-publishing/src/Semantic/HtmlBody.php index 0e785b4..bc61dce 100644 --- a/demos/blog-publishing/src/Semantic/HtmlBody.php +++ b/demos/blog-publishing/src/Semantic/HtmlBody.php @@ -5,7 +5,7 @@ namespace Be\Pattern\BlogPublishing\Semantic; use Be\Framework\Attribute\Validate; -use InvalidArgumentException; +use Be\Pattern\BlogPublishing\Exception\InvalidHtmlBodyException; /** * HtmlBody - Semantic validation @@ -18,7 +18,7 @@ final class HtmlBody public function validate(string $htmlBody): void { if (empty(trim(strip_tags($htmlBody)))) { - throw new InvalidArgumentException('HTML body cannot be empty'); + throw new InvalidHtmlBodyException(); } } } diff --git a/demos/blog-publishing/src/Semantic/Slug.php b/demos/blog-publishing/src/Semantic/Slug.php index e03dd1f..e36754c 100644 --- a/demos/blog-publishing/src/Semantic/Slug.php +++ b/demos/blog-publishing/src/Semantic/Slug.php @@ -5,7 +5,7 @@ namespace Be\Pattern\BlogPublishing\Semantic; use Be\Framework\Attribute\Validate; -use InvalidArgumentException; +use Be\Pattern\BlogPublishing\Exception\InvalidSlugException; /** * Slug - Semantic validation @@ -18,7 +18,7 @@ final class Slug public function validate(string $slug): void { if (!preg_match('/^[a-z0-9-]+$/', $slug)) { - throw new InvalidArgumentException('Invalid slug format'); + throw new InvalidSlugException(); } } } diff --git a/demos/user-registration/src/Exception/InvalidAvatarUrlException.php b/demos/user-registration/src/Exception/InvalidAvatarUrlException.php new file mode 100644 index 0000000..69ceda2 --- /dev/null +++ b/demos/user-registration/src/Exception/InvalidAvatarUrlException.php @@ -0,0 +1,16 @@ + 'Invalid avatar URL.', + 'ja' => 'アバターURLの形式が不正です。' +])] +final class InvalidAvatarUrlException extends DomainException +{ +} diff --git a/demos/user-registration/src/Exception/InvalidHashedPasswordException.php b/demos/user-registration/src/Exception/InvalidHashedPasswordException.php new file mode 100644 index 0000000..d861e10 --- /dev/null +++ b/demos/user-registration/src/Exception/InvalidHashedPasswordException.php @@ -0,0 +1,16 @@ + 'Invalid password hash format.', + 'ja' => 'パスワードハッシュの形式が不正です。' +])] +final class InvalidHashedPasswordException extends DomainException +{ +} diff --git a/demos/user-registration/src/Semantic/AvatarUrl.php b/demos/user-registration/src/Semantic/AvatarUrl.php index 7205b63..be48f92 100644 --- a/demos/user-registration/src/Semantic/AvatarUrl.php +++ b/demos/user-registration/src/Semantic/AvatarUrl.php @@ -5,7 +5,7 @@ namespace Be\Pattern\UserRegistration\Semantic; use Be\Framework\Attribute\Validate; -use InvalidArgumentException; +use Be\Pattern\UserRegistration\Exception\InvalidAvatarUrlException; /** * AvatarUrl - Semantic validation @@ -20,7 +20,7 @@ final class AvatarUrl public function validate(string $avatarUrl): void { if (filter_var($avatarUrl, FILTER_VALIDATE_URL) === false) { - throw new InvalidArgumentException('Invalid avatar URL'); + throw new InvalidAvatarUrlException(); } } } diff --git a/demos/user-registration/src/Semantic/HashedPassword.php b/demos/user-registration/src/Semantic/HashedPassword.php index 09d4526..b4174a0 100644 --- a/demos/user-registration/src/Semantic/HashedPassword.php +++ b/demos/user-registration/src/Semantic/HashedPassword.php @@ -5,7 +5,7 @@ namespace Be\Pattern\UserRegistration\Semantic; use Be\Framework\Attribute\Validate; -use InvalidArgumentException; +use Be\Pattern\UserRegistration\Exception\InvalidHashedPasswordException; /** * HashedPassword - Semantic validation @@ -19,7 +19,7 @@ public function validate(string $hashedPassword): void { // Bcrypt hashes start with $2y$ or $2a$ and are 60 characters if (!preg_match('/^\$2[aby]\$\d{2}\$.{53}$/', $hashedPassword)) { - throw new InvalidArgumentException('Invalid password hash format'); + throw new InvalidHashedPasswordException(); } } } From 10821e4fa641b77981f613d6f9c29ef8f1d53b4d Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Sat, 16 May 2026 17:52:41 +0900 Subject: [PATCH 3/4] Use 1.x-dev for be-framework/psalm-plugin The plugin repo's default branch was renamed main -> 1.x to match the Be Framework versioning convention (0.x, 1.x). Update each demo's require-dev constraint accordingly. --- demos/blog-publishing/composer.json | 2 +- demos/contact-form/composer.json | 2 +- demos/hello-world/composer.json | 2 +- demos/insurance-claim/composer.json | 2 +- demos/loan-application/composer.json | 2 +- demos/medical-triage/composer.json | 2 +- demos/order-processing/composer.json | 2 +- demos/user-registration/composer.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/demos/blog-publishing/composer.json b/demos/blog-publishing/composer.json index ba9b5e5..a9c6b1a 100644 --- a/demos/blog-publishing/composer.json +++ b/demos/blog-publishing/composer.json @@ -18,7 +18,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { diff --git a/demos/contact-form/composer.json b/demos/contact-form/composer.json index a9aa8f0..d4f56ff 100644 --- a/demos/contact-form/composer.json +++ b/demos/contact-form/composer.json @@ -18,7 +18,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { diff --git a/demos/hello-world/composer.json b/demos/hello-world/composer.json index 71d5ffa..f0b1870 100644 --- a/demos/hello-world/composer.json +++ b/demos/hello-world/composer.json @@ -18,7 +18,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { diff --git a/demos/insurance-claim/composer.json b/demos/insurance-claim/composer.json index 7b1e4ef..a75b2a4 100644 --- a/demos/insurance-claim/composer.json +++ b/demos/insurance-claim/composer.json @@ -17,7 +17,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { diff --git a/demos/loan-application/composer.json b/demos/loan-application/composer.json index c59475b..b1ecc44 100644 --- a/demos/loan-application/composer.json +++ b/demos/loan-application/composer.json @@ -17,7 +17,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { diff --git a/demos/medical-triage/composer.json b/demos/medical-triage/composer.json index 3781ab1..1a5f370 100644 --- a/demos/medical-triage/composer.json +++ b/demos/medical-triage/composer.json @@ -17,7 +17,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { diff --git a/demos/order-processing/composer.json b/demos/order-processing/composer.json index 41ed17c..6900217 100644 --- a/demos/order-processing/composer.json +++ b/demos/order-processing/composer.json @@ -17,7 +17,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { diff --git a/demos/user-registration/composer.json b/demos/user-registration/composer.json index 206ac45..6c56de4 100644 --- a/demos/user-registration/composer.json +++ b/demos/user-registration/composer.json @@ -19,7 +19,7 @@ "ray/di": "^2.18" }, "require-dev": { - "be-framework/psalm-plugin": "dev-main", + "be-framework/psalm-plugin": "1.x-dev", "phpunit/phpunit": "^12" }, "scripts": { From c4a6f091f78ab33324d4f030dca572b3fa226a06 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Sun, 17 May 2026 00:28:28 +0900 Subject: [PATCH 4/4] Enable CodeRabbit request-changes workflow Allows @coderabbitai approve / resolve commands to issue formal GitHub review states (Approve / Request changes) instead of plain comments, once this lands on the default branch. --- .coderabbit.yaml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..11bd52f --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,2 @@ +reviews: + request_changes_workflow: true