{
  "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"
  ]
}
