Skip to content

gate-23 rules 2-7: filename matchers flag CONSUMERS of the OR abstraction as duplicators (4 repos fail on wholly false evidence) #281

Description

@rubenvdlinde

Summary

Rules 2–7 of hydra-gates/scripts/lint-or-abstraction-anti-patterns.sh are find -iname matchers. A filename cannot distinguish an app-local implementation of an OpenRegister abstraction from a consumer of it — and the consumer is the target state ADR-022 is asking for. So the gate's strongest findings are, in several cases, apps that have already done the migration.

Measured across all 18 Conduction app repos at origin/development, 2026-08-09, gate package 34370f60f51155ef43d4585d6164cad9ffb69f3c.

Confirmed false positives

docudesk lib/EventListener/ApprovalStepListener.php — flagged consume-or-approval-workflow-fleet-wide ("app-local ApprovalChain/Step class found — consume OR ApprovalService instead"). It does exactly that. Its imports:

use OCA\OpenRegister\Event\ApprovalStepApprovedEvent;
use OCA\OpenRegister\Event\ApprovalStepCompletedEvent;
use OCA\OpenRegister\Event\ApprovalStepInitiatedEvent;
use OCA\OpenRegister\Event\ApprovalStepRejectedEvent;

It is a subscriber to OpenRegister's own approval events. This is the only finding in the repo, so docudesk hard-fails on 100% false evidence.

zaakafhandelapp lib/Controller/ZaakAuditTrailController.php — flagged consume-or-audit-trail-fleet-wide ("emit via OR AuditTrailMapper"). Its docblock:

Serves the ZGW audit trail of a zaak on /api/zrc/zaken/{zaak_uuid}/audit_trail, derived from the OpenRegister object audit trail of that zaak and mapped onto the ZGW Audittrail shape.

It reads OR's audit trail and maps it to a VNG-standard response shape. Also the only finding in the repo. Note Audittrail here is a standardised ZGW term — renaming the class to dodge the matcher would be wrong on its own terms.

shillinq lib/Listener/InnovatieboxAuditTrailListener.php — subscribes to OCA\OpenRegister\Event\ObjectCreatedEvent / ObjectUpdatedEvent.

openconnector lib/Service/AuthorizationService.php — flagged consume-or-rbac-fleet-wide. It is inbound request authentication for openconnector's own API surface (JWT / basic / OAuth bearer / API key), not RBAC over OR objects, and it already resolves consumers through OR's ObjectService. The rule already excludes *AuthenticationService* by name, which shows the author knew authn ≠ RBAC; this is the same species with a different suffix. Only finding in the repo.

Probable false positives (weaker, listed for triage)

  • launchpad lib/Service/PermissionService.php, RoleFeaturePermissionService.php — govern which dashboard widgets a role may see, via local DashboardMapper / WidgetPlacementMapper. Zero OpenRegister references. Not permissions over OR objects.
  • decidesk lib/Service/StateMachineValidator.php — matched by *StateMachine*.php. It is a pure validator of a process template's transition graph (dangling refs, unreachable states), not a workflow engine. Only finding in the repo.
  • shillinq lib/Service/AdministrationAuditTrailService.php — resolves OR's ObjectService. Arguably still duplication (it writes its own audit entries as OR objects rather than via AuditTrailMapper), so this one genuinely needs a human call.

Genuine findings (for contrast — the rules are not useless)

  • procest — 26 Tenant* classes, 5 workflow-engine classes, 4 audit classes. Real, large.
  • hermiq — 6-class tenant control plane.
  • doriath lib/Listener/AuditListener.php — zero OR references; writes to a local append-only store via OCA\Doriath\Service\AuditService.
  • launchpad — see above, needs a call.

Suggested direction (not implemented here)

Same shape as the rule-1 rewrite in #279: keep the filename match as the candidate set, then read the file to classify. A file that imports OCA\OpenRegister\Event\* or dispatches through OR's ObjectService/AuditTrailMapper is a consumer; print it as an info line rather than counting it. A file with zero OR references that owns its own mapper/table is the real target.

Deliberately not attempted under the four-day clock that prompted this measurement — narrowing a matcher in a hurry is how a gate gets widened by accident. The epoch move in #279 (to 2026-10-03) gives this an 8-week runway.

Why it matters now

With #279 merged, gate-23 findings stand at 10 of 18 repos in BLOCK mode. Of those, 4 fail on evidence that is entirely false (docudesk, zaakafhandelapp, openconnector, decidesk each have exactly one finding, and each is a misclassification). Flipping this gate blocking before that is fixed would fail four repos for having done the migration correctly.

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