Skip to content

docs: correct CSRF protection opt-in description#30

Open
koriym wants to merge 6 commits into
1.xfrom
claude/review-csrf-protection-yjrZA
Open

docs: correct CSRF protection opt-in description#30
koriym wants to merge 6 commits into
1.xfrom
claude/review-csrf-protection-yjrZA

Conversation

@koriym
Copy link
Copy Markdown
Member

@koriym koriym commented May 19, 2026

Summary

The README sections on CSRF protection claimed that SetAntiCsrfTrait only wires AntiCsrfInterface into the form and that token verification requires #[CsrfProtection]:

A form that uses SetAntiCsrfTrait is wired with an AntiCsrfInterface, but the token is only verified when the validated method is annotated with #[CsrfProtection]. Methods without #[CsrfProtection] perform no CSRF check even if the form supports it.

This is not what the code does.

SetAntiCsrfTrait::setAntiCsrf() is annotated with #[Inject], so DI populates $this->antiCsrf at construction. AbstractForm::postConstruct() then calls enableAntiCsrf() to add the token field, and AbstractForm::apply() throws CsrfViolationException on token mismatch — regardless of whether the controller method has #[CsrfProtection]. This is exercised by AbstractFormTest::testAntiCsrfViolation, which sets antiCsrf directly on the form (no interceptor, no attribute) and asserts the throw.

So there are two independent opt-in paths and the README/skill should describe them as such.

Changes

  • README.md / README.JA.md: rewrite the "CSRF Protections" intro to describe the two independent paths (per-form trait vs. per-action attribute) and state that either causes apply() to throw on mismatch.
  • .claude/skills/migrate-to-1.0/SKILL.md: replace the "out of scope" bullet that said forms using SetAntiCsrfTrait without #[CsrfProtection] "will silently stop enforcing CSRF in 1.0" — the actual at-risk case is the removed @FormValidation(antiCsrf=true) option when the form did not also use the trait.

Test plan

  • Manual reading: README example (use SetAntiCsrfTrait; + no #[CsrfProtection] on controller) is consistent with AbstractFormTest::testAntiCsrfViolation.
  • No code changes; existing tests still pass.

Generated by Claude Code

Summary by CodeRabbit

  • Documentation
    • Clarified CSRF protection is opt-in with two independent activation paths: per-form (SetAntiCsrfTrait) and per-action (#[CsrfProtection])
    • Reorganized examples into separate per-action and per-form guides; noted enabling both is harmless but redundant
    • Specified exception behavior on token mismatch and updated migration guidance after removal of the prior antiCsrf option, including note on redundant inserted attributes
    • Updated Japanese README accordingly
  • Chores
    • Lint config updated to require fenced code blocks

Review Change Stack

README claimed CSRF was only verified when #[CsrfProtection] was present,
but SetAntiCsrfTrait alone is sufficient: the trait's #[Inject] setter
populates $this->antiCsrf, postConstruct() calls enableAntiCsrf(), and
AbstractForm::apply() throws CsrfViolationException on token mismatch
regardless of the attribute (covered by AbstractFormTest::testAntiCsrfViolation).

Document the two independent opt-in paths (per-form trait, per-action
attribute) and fix the migrate-to-1.0 skill's "out of scope" note that
implied SetAntiCsrfTrait-only forms silently stop enforcing CSRF in 1.0.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7b94efaf-8799-4455-9286-048df11f647d

📥 Commits

Reviewing files that changed from the base of the PR and between b390a58 and 35e2425.

📒 Files selected for processing (1)
  • README.md
✅ Files skipped from review due to trivial changes (1)
  • README.md

📝 Walkthrough

Walkthrough

This PR updates documentation across three files to clarify CSRF protection behavior in the form module. The changes explain that CSRF protection is opt-in, available through two independent mechanisms—per-form via SetAntiCsrfTrait and per-action via #[CsrfProtection]—and detail when token validation and exceptions occur.

Changes

CSRF Protection Documentation Clarification

Layer / File(s) Summary
Migration guide clarifications
.claude/skills/migrate-to-1.0/SKILL.md
Clarifies that when @FormValidation(... antiCsrf=false) (or omitted) no #[CsrfProtection] is automatically added and that forms may still enforce CSRF via SetAntiCsrfTrait; updates guidance on whether #[CsrfProtection] added by the rewrite is redundant.
README (EN/JA) CSRF sections and examples
README.md, README.JA.md
Rewrites CSRF Protections sections to state CSRF is opt-in via per-form (use SetAntiCsrfTrait) or per-action (#[CsrfProtection]), documents that AbstractForm::apply() throws CsrfViolationException on token mismatch when enabled, and separates per-action and per-form example snippets.
Markdown lint configuration
.markdownlint.json
Adds an MD046 rule with "style": "fenced" to require fenced code blocks.

🎯 2 (Simple) | ⏱️ ~10 minutes

A rabbit nibbles on the docs at night,
Hops through CSRF paths to make them bright,
Per-form or per-action, both now clear,
Tokens checked, exceptions near,
Docs polished — hop, celebrate with delight! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'docs: correct CSRF protection opt-in description' accurately describes the primary change: documentation corrections clarifying CSRF protection as an opt-in feature with two independent mechanisms, replacing incorrect descriptions in README files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
  • Commit unit tests in branch claude/review-csrf-protection-yjrZA

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.

@koriym
Copy link
Copy Markdown
Member Author

koriym commented May 19, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

✅ Actions performed

Review triggered.

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.

@koriym koriym marked this pull request as ready for review May 19, 2026 07:09
@koriym koriym requested a review from Copilot May 19, 2026 07:09
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR corrects the project documentation around how CSRF protection is actually enabled/enforced in ray/web-form-module, aligning the READMEs and the bundled migration skill guidance with the current runtime behavior (notably AbstractForm::apply() and the existing tests).

Changes:

  • Updated README.md / README.JA.md CSRF section to describe two independent CSRF opt-in paths (per-form trait vs. per-action attribute) and the resulting CsrfViolationException behavior.
  • Updated the migration skill (.claude/.../SKILL.md) guidance to reflect the real “at-risk” migration scenario around the removed antiCsrf=true option.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
README.md Rewrites CSRF protection explanation to reflect actual enforcement behavior and the two opt-in paths.
README.JA.md Japanese equivalent of the CSRF documentation rewrite.
.claude/skills/migrate-to-1.0/SKILL.md Adjusts migration guidance around antiCsrf=true and how CSRF enforcement is preserved in 1.0.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
independent paths:

- **Per-form**: add `use SetAntiCsrfTrait;` to the form. `AntiCsrfInterface`
is injected at construction time, the token field is added in
Comment thread README.md Outdated
Comment on lines +145 to +149
CSRF protection is **opt-in** and can be enabled through either of two
independent paths:

- **Per-form**: add `use SetAntiCsrfTrait;` to the form. `AntiCsrfInterface`
is injected at construction time, the token field is added in
Comment thread README.JA.md Outdated
Comment on lines +130 to +134
CSRF対策は **opt-in** で、独立した 2 つの経路のいずれかで有効化できます。

- **フォーム単位**: フォームに `use SetAntiCsrfTrait;` を追加します。
DI で `AntiCsrfInterface` が注入され、`postConstruct()` でトークンフィールドが
追加され、`apply()` の呼び出しごとにトークンが検証されます。
Comment thread .claude/skills/migrate-to-1.0/SKILL.md Outdated
Comment on lines +197 to +203
- Migrating `@FormValidation(antiCsrf=true)` callers that did **not** use
`SetAntiCsrfTrait` on the form. These relied on the removed `antiCsrf`
option to enable CSRF; after dropping the option they need
`#[CsrfProtection]` on the validated method (or `SetAntiCsrfTrait` on
the form) to keep enforcement. Flag these to the user so they can decide.
Forms that already use `SetAntiCsrfTrait` continue to enforce CSRF in 1.0
via `AbstractForm::apply()` regardless of `#[CsrfProtection]`.
@koriym
Copy link
Copy Markdown
Member Author

koriym commented May 19, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

✅ Actions performed

Full review triggered.

- Reword "injected at construction time" to clarify the trait uses an
  #[Inject] setter (method injection by Ray.Di), not constructor injection.
- Split the README example into two minimal snippets — one per opt-in path —
  and note that combining both is redundant. The single combined example
  contradicted the "two independent paths" wording.
- Drop the migrate-to-1.0 "out of scope" bullet that overlapped with the
  automated Step 1b rewrite. Replace it with a note that #[CsrfProtection]
  added by 1b is redundant when the form already uses SetAntiCsrfTrait, so
  users can choose a single declaration site.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comment thread README.md Outdated
Comment on lines +174 to +178
// Per-form: declare CSRF on the form itself.
use Ray\WebFormModule\AbstractAuraForm;
use Ray\WebFormModule\SetAntiCsrfTrait;

class MyForm extends AbstractAuraForm
Comment thread README.JA.md Outdated
Comment on lines +159 to +163
// フォーム単位: フォーム自身で宣言。
use Ray\WebFormModule\AbstractAuraForm;
use Ray\WebFormModule\SetAntiCsrfTrait;

class MyForm extends AbstractAuraForm
Comment on lines +197 to +201
- Deciding whether `#[CsrfProtection]` added by Step 1b is redundant. Forms
that already use `SetAntiCsrfTrait` enforce CSRF via `AbstractForm::apply()`
regardless of the attribute, so the attribute Step 1b inserts is harmless
but unnecessary. Flag these to the user so they can drop the attribute if
they prefer a single declaration site.
- Split the README CSRF examples into two valid stand-alone code blocks
  (per-action and per-form). The previous single block had `use` statements
  after `class MyController`, which is not valid PHP in one file.
- Reword the Step 1b note ("methods without the attribute perform no CSRF
  check") so it no longer contradicts the Out-of-scope note about
  SetAntiCsrfTrait-only forms still enforcing CSRF via AbstractForm::apply().
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@README.JA.md`:
- Line 163: The markdownlint MD046 warning indicates a fenced PHP code block (`
```php `) is used but the repo expects indented code blocks; replace the fenced
block marker (` ```php ` and the closing ```` ``` ````) with an indented code
block by prefixing each line of the code sample with four spaces (or a single
tab) where the fenced block starts, ensuring the content that was between `
```php ` and its closing fence remains intact and correctly indented so the
linter treats it as an indented code block.
- Around line 164-168: Replace the nonexistent base class AbstractAuraForm with
the correct AbstractForm: change the use statement from
Ray\WebFormModule\AbstractAuraForm to Ray\WebFormModule\AbstractForm and update
the class declaration so MyForm extends AbstractForm (leave SetAntiCsrfTrait
as-is); ensure you import AbstractForm and adjust the extends clause in the
MyForm class.

In `@README.md`:
- Line 178: The README contains a fenced PHP code block using ```php which
triggers markdownlint MD046 expecting indented code blocks; update the block by
converting the fenced PHP block (the ```php fence) into an indented code block
(prefix each code line with four spaces) or alternatively adjust the
repository's markdownlint config to allow fenced blocks for PHP, ensuring the
fenced ```php instance is replaced or made compliant with MD046.
- Around line 179-183: The README references a non-existent class
AbstractAuraForm; replace occurrences of AbstractAuraForm with AbstractForm by
updating the use statement (change use Ray\WebFormModule\AbstractAuraForm; to
use Ray\WebFormModule\AbstractForm;) and the class declaration (change class
MyForm extends AbstractAuraForm to class MyForm extends AbstractForm) so the
example matches the library API.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4db0596e-5966-46ae-8962-eae37fba59e5

📥 Commits

Reviewing files that changed from the base of the PR and between 601f9b8 and 9722f7e.

📒 Files selected for processing (3)
  • .claude/skills/migrate-to-1.0/SKILL.md
  • README.JA.md
  • README.md
✅ Files skipped from review due to trivial changes (1)
  • .claude/skills/migrate-to-1.0/SKILL.md

Comment thread README.JA.md

フォーム単位 — フォーム自身で宣言:

```php
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

markdownlint MD046 の警告を解消してください。

Line 163 のコードブロックが Expected: indented; Actual: fenced と報告されています。CI ルールに合わせてブロックスタイルを統一してください。

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 163-163: Code block style
Expected: indented; Actual: fenced

(MD046, code-block-style)

🤖 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 `@README.JA.md` at line 163, The markdownlint MD046 warning indicates a fenced
PHP code block (` ```php `) is used but the repo expects indented code blocks;
replace the fenced block marker (` ```php ` and the closing ```` ``` ````) with
an indented code block by prefixing each line of the code sample with four
spaces (or a single tab) where the fenced block starts, ensuring the content
that was between ` ```php ` and its closing fence remains intact and correctly
indented so the linter treats it as an indented code block.

Comment thread README.JA.md Outdated
Comment thread README.md

Per-form — declare CSRF on the form itself:

```php
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Address markdownlint MD046 on this new fenced block.

Line 178 is currently flagged (Expected: indented; Actual: fenced). If CI enforces this rule, convert this block style to match repository markdownlint configuration.

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 178-178: Code block style
Expected: indented; Actual: fenced

(MD046, code-block-style)

🤖 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 `@README.md` at line 178, The README contains a fenced PHP code block using
```php which triggers markdownlint MD046 expecting indented code blocks; update
the block by converting the fenced PHP block (the ```php fence) into an indented
code block (prefix each code line with four spaces) or alternatively adjust the
repository's markdownlint config to allow fenced blocks for PHP, ensuring the
fenced ```php instance is replaced or made compliant with MD046.

Comment thread README.md Outdated
claude added 2 commits May 19, 2026 11:03
src/AbstractForm.php only declares AbstractForm; AbstractAuraForm does
not exist in this package. The example was inherited from the original
CSRF section and never compiled.
README.md and README.JA.md already use fenced code blocks throughout
(20+ and 24+ occurrences). The default MD046 rule infers the style
from whichever block appears first, so the fenced blocks were
reported as errors. Pin the style to fenced to match the established
convention.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@README.md`:
- Around line 186-187: Add a blank line after the closing fenced code block
shown in the diff (the triple backticks that end the php example using
SetAntiCsrfTrait) so that the following prose ("You can provide your custom
`AntiCsrf` class...") is separated by one empty line; this fixes the
markdownlint MD031 error by ensuring there is an empty line between the fenced
code block and the subsequent paragraph.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6dc2f4a5-3d1a-4313-a06d-e4e596d2e8bc

📥 Commits

Reviewing files that changed from the base of the PR and between 9722f7e and b390a58.

📒 Files selected for processing (3)
  • .markdownlint.json
  • README.JA.md
  • README.md
✅ Files skipped from review due to trivial changes (2)
  • .markdownlint.json
  • README.JA.md

Comment thread README.md
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found.

Satisfies markdownlint MD031 (blanks-around-fences) for the fenced
block introduced in the CSRF section.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants