test(architecture): drop stale actionFragmentContext mentions

Cleanup follow-up to commit 9ec10f5, which removed the unused
actionFragmentContext aggregator and its building block. Two
architecture tests still mentioned the removed aggregator in their
allowlists and recognizer regexes — patterns that now match an empty
set, harmless but misleading.

* ActionContextCsrfPairingContractTest: drop 'actionFragmentContext'
  from the AGGREGATORS constant, update the docblock to list only the
  two remaining aggregators, and rewrite the GET-only-allowlist
  comment to no longer reference the fragment-specific case (the
  guard itself stays — any future GET-only aggregator caller would
  still hit it).
* DetailDrawerFragmentContractTest: drop the third alternative from
  the aggregator-recognizer regex inside extractTopLevelAbility, and
  trim two comments accordingly.

The historical documentation in ActionContextHelperContractTest is
deliberately kept — those comments explain to future readers why the
test only freezes 5 building blocks and 2 aggregators (instead of
the original 6/3) and why the CSRF-warning expectation is 2 instead
of 3. That is contextual documentation, not stale references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-26 17:47:36 +02:00
parent 9ec10f5c02
commit 01f5265eff
2 changed files with 11 additions and 12 deletions

View File

@@ -9,9 +9,9 @@ use RecursiveIteratorIterator;
/**
* GR-SEC-001 extension: every page action that calls one of the
* action-context aggregators (actionEditContext, actionCreateContext,
* actionFragmentContext) AND handles POST data MUST also call
* actionRequireCsrf() before it accesses the request body.
* action-context aggregators (actionEditContext, actionCreateContext)
* AND handles POST data MUST also call actionRequireCsrf() before it
* accesses the request body.
*
* Closes plan-stage finding SEC-PLAN-004 from Run
* 2026-04-25-action-context-helper. Replaces the obsolete
@@ -39,7 +39,6 @@ class ActionContextCsrfPairingContractTest extends TestCase
private const AGGREGATORS = [
'actionEditContext',
'actionCreateContext',
'actionFragmentContext',
];
/**
@@ -106,8 +105,8 @@ class ActionContextCsrfPairingContractTest extends TestCase
$isPostHandler = $this->hasAny($content, self::POST_PRESENCE_INDICATORS)
|| preg_match('/->body\(/', $content) === 1;
// Drawer-fragment allowlist: actionFragmentContext-only callers
// without any POST indicator are GET-only and don't need CSRF.
// GET-only allowlist: aggregator callers without any POST
// indicator are render-only and don't need CSRF.
if (!$isPostHandler) {
continue;
}

View File

@@ -192,10 +192,10 @@ class DetailDrawerFragmentContractTest extends TestCase
* argument from a PHP source string. Returns null and records a violation
* when no statically extractable call is found.
*
* Also recognizes the actionEditContext / actionCreateContext / actionFragmentContext
* aggregator pattern: if the file calls one of those aggregators at top level,
* we look for an 'abilityKey' => SomePolicy::CONST entry inside the args array
* and treat it as the top-level ability.
* Also recognizes the actionEditContext / actionCreateContext aggregator
* pattern: if the file calls one of those aggregators at top level, we
* look for an 'abilityKey' => SomePolicy::CONST entry inside the args
* array and treat it as the top-level ability.
*/
private function extractTopLevelAbility(string $source, string $fileRel, array &$violations): ?string
{
@@ -224,11 +224,11 @@ class DetailDrawerFragmentContractTest extends TestCase
$hasNestedMatch = true;
}
}
// actionEditContext / actionCreateContext / actionFragmentContext aggregator pattern.
// actionEditContext / actionCreateContext aggregator pattern.
// The aggregator args use a [ ... ] array literal (not a { ... } block),
// so brace-depth tracking does not bracket them; we track the array
// opening with a separate "inside aggregator args" sticky flag instead.
if (!$insideTopLevelAggregator && $depth === 0 && preg_match('/actionEditContext\s*\(|actionCreateContext\s*\(|actionFragmentContext\s*\(/', $line)) {
if (!$insideTopLevelAggregator && $depth === 0 && preg_match('/actionEditContext\s*\(|actionCreateContext\s*\(/', $line)) {
$insideTopLevelAggregator = true;
}
if ($insideTopLevelAggregator && !$hasTopLevelMatch && preg_match('/[\'"]abilityKey[\'"]\s*=>\s*([A-Za-z_\\\\][A-Za-z0-9_\\\\:]*)/', $line, $am)) {