1
0

refactor(actions): centralize wave-2 post/csrf guards

This commit is contained in:
2026-04-24 18:31:17 +02:00
parent cfd867bcd7
commit da7e7c593e
26 changed files with 237 additions and 114 deletions

View File

@@ -0,0 +1,95 @@
{
"task_id": "2026-04-24-action-csrf-centralization-step2",
"plan_ref": ".agents/runs/2026-04-24-action-csrf-centralization-step2/plan.json",
"status": "done",
"changed_files": [
{ "path": "core/Support/helpers/request.php", "summary": "Extended actionRequireCsrf() with optional redirectOnFailure flag for non-redirect POST flows." },
{ "path": "pages/admin/settings/revoke-api-tokens().php", "summary": "Replaced inline POST/CSRF boilerplate with actionRequirePost/actionRequireCsrf." },
{ "path": "pages/admin/settings/expire-remember-tokens().php", "summary": "Replaced inline POST/CSRF boilerplate with actionRequirePost/actionRequireCsrf." },
{ "path": "pages/admin/scheduled-jobs/purge-runs().php", "summary": "Replaced inline POST/CSRF boilerplate with actionRequirePost/actionRequireCsrf." },
{ "path": "pages/admin/scheduled-jobs/run($id).php", "summary": "Centralized method/CSRF guards via actionRequirePost/actionRequireCsrf." },
{ "path": "pages/admin/tenants/custom-field-create($id).php", "summary": "Centralized method/CSRF guard flow via action helpers." },
{ "path": "pages/admin/tenants/custom-field-update($id).php", "summary": "Centralized method/CSRF guard flow via action helpers." },
{ "path": "pages/admin/tenants/custom-field-delete($id).php", "summary": "Centralized method/CSRF guard flow via action helpers." },
{ "path": "pages/admin/users/access-pdf($id).php", "summary": "Kept GET rendering path intact; centralized CSRF check only in POST branch." },
{ "path": "pages/admin/users/access-pdf-bulk().php", "summary": "Replaced inline POST/CSRF boilerplate with actionRequirePost/actionRequireCsrf." },
{ "path": "pages/admin/departments/create().php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/departments/edit($id).php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/permissions/create().php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/permissions/edit($id).php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/roles/create().php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/roles/edit($id).php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/tenants/create().php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/tenants/edit($id).php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/users/edit($id).php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/settings/index().php", "summary": "Replaced inline CSRF block with actionRequireCsrf in POST branch." },
{ "path": "pages/admin/scheduled-jobs/edit($id).php", "summary": "Centralized CSRF validation via actionRequireCsrf(..., redirectOnFailure: false) while preserving in-page error rendering." }
],
"guard_evidence": [
{
"guard_id": "GR-CORE-003",
"status": "pass",
"evidence": "Refactor keeps requestInput()-based handling; no superglobal request/session access introduced."
},
{
"guard_id": "GR-CORE-012",
"status": "pass",
"evidence": "PRG flows in targeted actions remain intact; PostRedirectGetContractTest passes."
},
{
"guard_id": "GR-SEC-001",
"status": "pass",
"evidence": "All Wave-2 targets now verify CSRF through actionRequireCsrf (or non-redirect variant in scheduled-jobs/edit)."
},
{
"guard_id": "GR-SEC-008",
"status": "pass",
"evidence": "Existing policy/ability checks remain unchanged; only guard boilerplate was centralized."
},
{
"guard_id": "GR-SEC-009",
"status": "pass",
"evidence": "Tenant-scope related service and authorization calls were not altered."
},
{
"guard_id": "GR-TEST-001",
"status": "pass",
"evidence": "Architecture test set and full PHPUnit suite pass."
}
],
"commands": [
{ "cmd": "docker compose exec -T php vendor/bin/phpunit tests/Architecture/PostEndpointCsrfContractTest.php", "result": "pass" },
{ "cmd": "docker compose exec -T php vendor/bin/phpunit tests/Architecture/PostRedirectGetContractTest.php", "result": "pass" },
{ "cmd": "docker compose exec -T php vendor/bin/phpunit tests/Architecture/AuthzAdminSettingsContractTest.php tests/Architecture/AuthzAdminMasterDataContractTest.php tests/Architecture/AuthzAdminUsersContractTest.php", "result": "pass" },
{ "cmd": "docker compose exec -T php vendor/bin/phpunit", "result": "pass" },
{ "cmd": "docker compose exec -T php vendor/bin/phpstan analyse -c phpstan.neon --no-progress", "result": "pass" },
{ "cmd": "docker compose exec -T php vendor/bin/phpunit tests/Architecture/CoreStarterkitContractTest.php", "result": "pass" },
{ "cmd": "docker compose exec -T php vendor/bin/php-cs-fixer fix --config=tools/php-cs-fixer/.php-cs-fixer.dist.php --dry-run --diff --verbose", "result": "pass" },
{ "cmd": "bin/docs-link-check.sh", "result": "pass" },
{ "cmd": "bin/docs-drift-check.sh", "result": "pass" },
{ "cmd": "bin/codex-skills-sync.sh --check", "result": "pass" }
],
"quality_gate_results": [
{ "gate_id": "QG-001", "result": "pass", "notes": "PHPUnit full run green: 2023 tests, 28224 assertions." },
{ "gate_id": "QG-002", "result": "pass", "notes": "PHPStan level 5: no errors." },
{ "gate_id": "QG-003", "result": "pass", "notes": "CoreStarterkitContractTest green: 13 tests, 6974 assertions." },
{ "gate_id": "QG-006", "result": "pass", "notes": "php-cs-fixer dry-run green after removing one unused import." },
{ "gate_id": "QG-008", "result": "pass", "notes": "docs-link-check and docs-drift-check green." },
{ "gate_id": "QG-009", "result": "pass", "notes": "codex-skills-sync --check green." }
],
"metrics": {
"wave2_target_files": 20,
"before_requestinput_method_calls": 9,
"after_requestinput_method_calls": 0,
"before_inline_session_csrf_checks": 20,
"after_inline_session_csrf_checks": 0
},
"test_results": [
{ "name": "PostEndpointCsrfContractTest", "result": "pass", "notes": "1 test, 2 assertions." },
{ "name": "PostRedirectGetContractTest", "result": "pass", "notes": "1 test, 2 assertions." },
{ "name": "Authz Admin contract suite", "result": "pass", "notes": "13 tests, 203 assertions." },
{ "name": "CoreStarterkitContractTest", "result": "pass", "notes": "13 tests, 6974 assertions." },
{ "name": "Full PHPUnit suite", "result": "pass", "notes": "2023 tests, 28224 assertions." }
],
"open_items": []
}

View File

@@ -0,0 +1,12 @@
{
"task_id": "2026-04-24-action-csrf-centralization-step2",
"ready_to_finalize": true,
"code_review": "pass",
"security_review": "pass",
"acceptance_review": "pass",
"ci_status": "required-gates-pass",
"final_action": "commit",
"hold_reason": "",
"commit_message": "refactor(actions): centralize wave-2 post/csrf guards",
"notes": "Wave 2.1 + 2.2 executed. Required gates QG-001/002/003/006/008/009 green."
}

View File

@@ -0,0 +1,44 @@
{
"task_id": "2026-04-24-action-csrf-centralization-step2",
"verdict": "pass",
"checked_criterion_ids": [
"SC-001",
"SC-002",
"SC-003",
"SC-004",
"SC-005"
],
"checks": [
{
"criterion_id": "SC-001",
"criterion": "All Wave-2.1/2.2 targets use actionRequirePost() and actionRequireCsrf() where semantically applicable without changing endpoint behavior.",
"result": "pass",
"evidence": "All planned Wave-2 targets were migrated to helper-based method/CSRF guards; mixed GET/POST access-pdf endpoint kept GET path unchanged."
},
{
"criterion_id": "SC-002",
"criterion": "No regressions in PRG/authz flows: PostRedirectGetContractTest and Authz architecture suites remain green.",
"result": "pass",
"evidence": "PostRedirectGetContractTest and AuthzAdminSettings/AuthzAdminMasterData/AuthzAdminUsers contract tests pass."
},
{
"criterion_id": "SC-003",
"criterion": "POST actions without CSRF/helper remain 0 in pages/ after the change.",
"result": "pass",
"evidence": "PostEndpointCsrfContractTest passes with no missing POST handlers."
},
{
"criterion_id": "SC-004",
"criterion": "Inline method-check and inline CSRF-check occurrences in Wave-2 scope are reduced substantially (target: method checks -60%+, csrf checks -60%+ in targeted files).",
"result": "pass",
"evidence": "Wave-2 file metrics: requestInput()->method() 9 -> 0, Session::checkCsrfToken() 20 -> 0."
},
{
"criterion_id": "SC-005",
"criterion": "Required gate set QG-001/002/003/006/008/009 passes; non-scope qa-required extras are reported separately if failing.",
"result": "pass",
"evidence": "All required gates were run individually and passed."
}
],
"missing_or_wrong": []
}

View File

@@ -0,0 +1,18 @@
{
"task_id": "2026-04-24-action-csrf-centralization-step2",
"verdict": "pass",
"checked_guard_ids": [
"GR-CORE-003",
"GR-CORE-012",
"GR-TEST-001"
],
"checked_quality_gate_ids": [
"QG-001",
"QG-002",
"QG-003",
"QG-006",
"QG-008",
"QG-009"
],
"findings": []
}

View File

@@ -0,0 +1,10 @@
{
"task_id": "2026-04-24-action-csrf-centralization-step2",
"verdict": "pass",
"checked_guard_ids": [
"GR-SEC-001",
"GR-SEC-008",
"GR-SEC-009"
],
"findings": []
}