Skip to content

Derive REST permission_callback from controller middleware#38

Merged
alexstandiford merged 1 commit into
mainfrom
fix/declarative-permission-callback
Jun 12, 2026
Merged

Derive REST permission_callback from controller middleware#38
alexstandiford merged 1 commit into
mainfrom
fix/declarative-permission-callback

Conversation

@alexstandiford

Copy link
Copy Markdown
Contributor

Implements the design from #31: the permission callback runs the same middleware chain the route uses — zero contract change. 401/403 → WP_Error at the gate; validation/existence failures keep the legacy error shape; WeakMap memoization runs the chain exactly once per request. Four new contract tests; suite 63 green. Fixes #31.

Every route registered with permission_callback => '__return_true',
which makes WordPress advertise all endpoints (including destructive
ones) as public and hides the real authorization from scanners and
reviewers — the most-flagged REST pattern in wp.org review.

The permission callback now runs the controller's own getMiddleware()
chain — no controller contract change. Authorization rejections
(RestException 401/403) surface as WP_Error at the permission gate, so
WordPress treats the route as protected. Non-auth middleware failures
(validation 422, existence 404) pass the gate and re-throw in the route
callback, preserving the legacy {error:{message,context}} payload shape
clients parse for rich validation detail. Per-request WeakMap
memoization guarantees the chain runs exactly once (middleware may
mutate request state). Controllers without middleware remain public,
exactly as before.

Declares php >=8.0 (WeakMap).

Fixes #31
@alexstandiford alexstandiford merged commit 28f855d into main Jun 12, 2026
1 check passed
@alexstandiford alexstandiford deleted the fix/declarative-permission-callback branch June 12, 2026 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RestStrategy registers all routes with permission_callback => __return_true

1 participant