Skip to content

The get-entry gate asks about the entry's form, not the blanket question - #50

Merged
AllTerrainDeveloper merged 1 commit into
mainfrom
fix/get-entry-permission-asks-about-the-form
Sep 6, 2026
Merged

AllTerrainDeveloper merged 1 commit into
mainfrom
fix/get-entry-permission-asks-about-the-form

Conversation

@AllTerrainDeveloper

Copy link
Copy Markdown
Owner

What

The wordpress.org reviewer flagged allterrain-forms/get-entry: its permission_callback checked only blanket entry-read access and did not authorise the target entry's form.

In practice nothing leaked -- alltfo_prepare_entry() re-asks the per-form alltfo_can_read_entries filter with the entry's form and returns nothing when denied -- but the declared gate is what an MCP client and the Abilities REST channel consult before executing, and it answered yes to entries the ability would then refuse. The /entries/{id} REST route had the same shape.

Change

  • New alltfo_can_read_entry( $entry_id ) in includes/post-types.php: resolves the entry to its form and asks the per-form filter about that form. A non-entry id falls back to the blanket question so a capable caller still gets its own "does not exist" answer rather than an opaque refusal.
  • get-entry ability gates on it (includes/abilities.php).
  • alltfo_rest_can_read_entries() gates /entries/{id} on it too, while /forms/{id}/analytics keeps treating id as the form (includes/rest.php).

Tests

  • test_per_form_filter_confines_the_read_abilities now seeds an entry in an allowed and a denied form and asserts check_permissions() itself refuses the denied one, and that execute() still returns a WP_Error.
  • test_analytics_permission_asks_about_the_right_form now expects the entry route to be denied at the gate when its form is denied, and still asserts the entry id is never mistaken for a form id.
  • New test_reading_one_entry_asks_about_its_form covers the helper and its fallback.
  • Full PHPUnit suite: 750 tests, 3561 assertions, green. PHPCS: no errors on touched files.

Docs

docs/abilities.md and docs/hooks-reference.md describe the per-form gating of get-entry and the /entries/{id} route.

🤖 Generated with Claude Code

https://claude.ai/code/session_01T7rWsbxZpSLqBqd2DtDGUY

The wordpress.org review flagged that the `get-entry` ability's
permission callback checked only whether the caller may read entries at
all. The data path behind it -- `alltfo_prepare_entry()` -- already
refused an entry whose form the per-form `alltfo_can_read_entries`
filter denies, so nothing leaked; but the declared gate is what an MCP
client consults before running anything, and it said "yes" to entries
it would then decline to return.

`alltfo_can_read_entry( $entry_id )` resolves an entry to its form and
asks the filter about that form. The `get-entry` ability and the
`/entries/{id}` REST route -- which had the same shape, deliberately
keeping the entry id out of the form question but asking about form 0
instead -- both gate on it now. An id that is not an entry falls back to
the blanket question so a capable caller still reaches its own "does not
exist" answer.

Tests cover the gate directly through `check_permissions()`, the REST
callback on an entry of a denied form, and the helper's fallback; the
abilities and hooks docs describe the per-form behaviour of get-entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T7rWsbxZpSLqBqd2DtDGUY
@AllTerrainDeveloper
AllTerrainDeveloper merged commit f4b2be7 into main Sep 6, 2026
3 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the fix/get-entry-permission-asks-about-the-form branch September 6, 2026 15:18
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.

1 participant