Skip to content

Conditional visibility is never enforced: checkRulesForPlacement() has no render-time caller, so preview says Hidden and the dashboard shows the widget anyway #98

Description

@rubenvdlinde

Summary

Conditional visibility is never enforced. Rules can be created, listed, edited and previewed, and none of it changes what any user sees. ConditionalService::checkRulesForPlacement() is called from exactly one place in production — the endpoint that reports a placement's rules — and from no dashboard or placement read path.

This makes REQ-CVUI-005's central guarantee false today:

the preview visible verdict MUST equal the render-time visibility verdict
AND this equality MUST hold because both paths execute the same evaluation code

There is no second path.

Three independent observations, in the order they were taken

1. Browser. Save an include rule with window 2020-01-01 .. 2020-12-31 through the Visibility rules editor, reload the dashboard: the placement still renders. The editor previews the very same rule set as Hidden a moment earlier, in the same modal.

2. HTTP, status code printed. Seed the same rule through the API and read the dashboard back:

POST /index.php/apps/launchpad/api/widgets/239/rules
{"ruleType":"date","ruleConfig":{"startDate":"2020-01-01","endDate":"2020-12-31"},"isInclude":true}
  -> 201

GET  /index.php/apps/launchpad/api/dashboard/43
  -> 200
placements: id=235 isVisible=1 | id=239 isVisible=1 (VISPROBE) | id=236 … | id=237 … | id=238 …

Placement 239 carries an include rule that cannot match, and comes back with isVisible: 1.

3. Callers.

$ grep -rn "checkRulesForPlacement" lib/
lib/Controller/RuleApiController.php:98:    $isVisible = $this->conditionalService->checkRulesForPlacement(
lib/Service/ConditionalService.php:93:     public function checkRulesForPlacement(int $placementId, string $userId): bool
lib/Service/VisibilityChecker.php:47:      * callers (`ConditionalService::checkRulesForPlacement()`) keep calling
lib/Service/RuleEvaluatorService.php:58:   * (`ConditionalService::checkRulesForPlacement()`) never pass them, so

The single production caller is RuleApiController::getRules() — the editor's own read, which is why GET /api/widgets/{id}/rules correctly answers {"rules":[…],"isVisible":…}. No dashboard controller, no placement serialiser, no initial-state provider calls it.

grep -rn "isWidgetVisible" lib/ returns nothing, so the render-time entry point REQ-CVUI-005 names by that name does not exist either.

Observation 3 is an absence claim, so it was taken with a positive control: the same grep for previewRules finds its caller (VisibilityPreviewController.php:123) immediately. The search works; there is nothing to find.

Note that two docblocks assert the opposite — VisibilityChecker.php:47 and RuleEvaluatorService.php:56-58 both describe "render-time callers (ConditionalService::checkRulesForPlacement())". They describe a caller that was never written. That is very likely how this survived review.

Severity

Conditional visibility is presented to authors as a working feature: the editor loads, saves, and gives a confident Visible / Hidden verdict with a matched-rule explanation. An author who scopes a widget to a group, or to a date window, will reasonably believe the widget is hidden from everyone else. It is not — it renders for every user with access to the dashboard.

If any rule anywhere was intended to keep content away from an audience, that expectation is not being met. Worth checking whether any live dashboard relies on it before this is prioritised.

Relationship to the other two

All three were found writing gate-19 round-3 coverage for conditional-visibility-editor. Together they mean the capability is, end to end, an editor over data nothing reads.

Impact on gate-19

Two scenarios cannot be covered and are left uncovered and NOT @e2e excluded (an exclusion claims a browser cannot observe the scenario; a browser is exactly what observed it failing, and per .github#345 the gate would score the exclusion as positive coverage):

  • REQ-CVUI-001 editor-does-not-change-evaluation-semantics
  • REQ-CVUI-005 preview-verdict-matches-render-time-verdict-for-identical-inputs

Both are recorded in tests/e2e/conditional-visibility-editor.spec.ts where the tests would otherwise sit, including the evidence above, so the next person does not have to rediscover it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions