Problem/Motivation

An API client cannot tell which fields this module guards. A write to a guarded field fails with a clear 403, but only after the client has built and sent the request. A read is worse: JSON:API leaves a view-denied field out of the resource with no marker, and GraphQL returns null, so a guarded field looks exactly like an empty one. Tools that sample entities to describe a bundle never see the field at all.

The module knows the answer. ProtectedFieldMap holds the map, and the access hook already decides whether an account holds the permission a guard names.

Proposed resolution

Add an optional submodule, field_guard_mcp, with two read-only Tool API plugins. It depends on Tool API and MCP Sentinel. The base module gains no dependency.

  • field_guard_list_guarded: for an entity type and optional bundle, the guarded fields, the operations guarded (view, edit) and the permission each one requires. Names only, never values.
  • field_guard_check_access: for the acting account only, whether it may view or edit each of up to 50 named fields on a bundle, so a client can check before it writes.

Move the explicit-permission check out of the underscore-prefixed function in the module file into a service method, so the hook, the tools and other modules share one implementation.

Not tools, by design: any write to the protected map or to role permissions (a reviewed config change is what the module's separation of duties rests on), reading guarded values (that would be the guard's bypass), checking access for an arbitrary user (a grant oracle), and own-subject resolution for an arbitrary entity (an ownership oracle).

Remaining tasks

  • Kernel tests: discovery and direct execution, anonymous and wrong-permission refusal, governance not ready, the check tool answers for the acting account only, no field value in any output.
  • CI step for the optional submodule.
  • README section and CHANGELOG entry.
  • The submodule declares only the core versions that MCP Sentinel also supports. The base module keeps its own range.

API changes

One new public service method for the explicit-permission check. The function stays as a wrapper.

Comments

jmcerda created an issue. See original summary.

jmcerda’s picture

Status: Active » Fixed

Committed to 1.x. The optional field_guard_mcp submodule ships in 1.3.0 with two read-only tools: field_guard_list_guarded and field_guard_check_access, which answers for the acting account only. The explicit-permission rule moved into the field_guard.explicit_permission_checker service; the function stays as a wrapper. Run database updates after deploying, so the container is rebuilt before the access hook asks for the new service.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • jmcerda committed 08a36577 on 1.x
    test: cover in-code revalidation and the list bound (#3624447)
    
    Follow-...

  • jmcerda committed 0abe3cc7 on 1.x
    feat: add optional field_guard_mcp tools submodule (#3624447)
    
    Two read-...