Files

93 lines
3.9 KiB
JSON

{
"task_id": "2026-04-24-action-csrf-centralization-step3",
"analysis_ref": ".agents/runs/2026-04-24-action-csrf-centralization-step3/analysis.json",
"summary": "Final wave to complete POST/CSRF guard centralization for all remaining admin actions, including JSON/data endpoints and architecture enforcement for future drift prevention.",
"scope": {
"in": [
"Extend actionRequirePost/actionRequireCsrf for JSON status/payload and forceJson use-cases",
"Migrate all remaining inline method/csrf checks in pages/admin to helper-based guards",
"Add architecture test that forbids direct requestInput()->method() and Session::checkCsrfToken() usage in pages/admin",
"Run required quality gates and admin-related architecture checks"
],
"out": [
"Non-admin core pages",
"Module pages under modules/*/pages",
"Business-logic changes in services/repositories"
]
},
"guardrails": {
"required_guard_ids": [
"GR-CORE-003",
"GR-CORE-012",
"GR-SEC-001",
"GR-SEC-008",
"GR-SEC-009",
"GR-TEST-001"
],
"required_quality_gate_ids": [
"QG-001",
"QG-002",
"QG-003",
"QG-006",
"QG-008",
"QG-009"
]
},
"success_criteria": [
{
"id": "SC-001",
"criterion": "All remaining pages/admin inline method checks are replaced by actionRequirePost() or requestInput()->isMethod('POST') + actionRequireCsrf() patterns."
},
{
"id": "SC-002",
"criterion": "All remaining pages/admin inline Session::checkCsrfToken() checks are replaced by actionRequireCsrf()."
},
{
"id": "SC-003",
"criterion": "New architecture contract prevents reintroduction of direct requestInput()->method() and Session::checkCsrfToken() in pages/admin."
},
{
"id": "SC-004",
"criterion": "CSRF and PRG architecture tests remain green and authz admin contract suites remain green."
},
{
"id": "SC-005",
"criterion": "Required quality gate set QG-001/002/003/006/008/009 passes."
}
],
"implementation_steps": [
{
"id": "S1",
"title": "Helper capability extension",
"description": "Add optional JSON status/payload and forceJson flags to actionRequirePost/actionRequireCsrf without breaking existing callers."
},
{
"id": "S2",
"title": "Remaining admin endpoint migration",
"description": "Refactor users/theme, users/switch-tenant, session-ping/data, tenants/ldap-test-connection/data, users/create, users/bulk, users/api-token-create, users/api-token-revoke, imports/index."
},
{
"id": "S3",
"title": "Architecture hardening",
"description": "Add and run admin contract test to enforce helper-based guards in pages/admin going forward."
},
{
"id": "S4",
"title": "Verification and gate execution",
"description": "Run targeted architecture checks and full required gates; capture metrics and run artifacts."
}
],
"tests": [
"docker compose exec -T php vendor/bin/phpunit tests/Architecture/AdminActionRequestGuardContractTest.php",
"docker compose exec -T php vendor/bin/phpunit tests/Architecture/PostEndpointCsrfContractTest.php tests/Architecture/PostRedirectGetContractTest.php",
"docker compose exec -T php vendor/bin/phpunit tests/Architecture/AuthzAdminSettingsContractTest.php tests/Architecture/AuthzAdminMasterDataContractTest.php tests/Architecture/AuthzAdminUsersContractTest.php",
"docker compose exec -T php vendor/bin/phpunit",
"docker compose exec -T php vendor/bin/phpstan analyse -c phpstan.neon --no-progress",
"docker compose exec -T php vendor/bin/phpunit tests/Architecture/CoreStarterkitContractTest.php",
"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",
"bin/docs-link-check.sh",
"bin/docs-drift-check.sh",
"bin/codex-skills-sync.sh --check"
]
}