Skip to content

Author entity access rules (GRANT) over MCP/PED via domain-model path-ops; security role/user docs are sealed #704

Description

@ako

Summary

Implemented in this change: GRANT entity access rules over the MCP/PED backend. Filing to record the finding, the scope, and the follow-ups.

While probing whether PED's "no security write path" is real (after #699 showed navigation was just unwired), we found "security" is two different things over PED:

  • Sealedped_read_document on Security$ProjectSecurity and Security$ModuleSecurity both return "Unknown document type". So module roles, user roles, demo users, and project security settings genuinely cannot be authored over MCP.
  • Reachable — an entity's access rules are not in the security document; they live on DomainModels$Entity.accessRules (the domain-model document PED already authors). Verified live on 11.12: moduleRoles, per-member attribute/association refs, and access rights are the same qualified names mxcli already builds, so EntityAccessRuleParams maps 1:1 onto a DomainModels$AccessRule constructor add.

What shipped

mdl/backend/mcp/security.goAddEntityAccessRule over PED:

  • Reads the entity's existing rules, builds the DomainModels$AccessRule constructor (moduleRoles + memberAccesses + allowCreate/Delete + defaultMemberAccessRights + xPathConstraint), and adds it at /entities/N/accessRules, gated by ped_check_errors.
  • The executor already builds the complete member-access list (every attribute + FROM-side associations + system owner/changedBy, per the CE0066 FROM-entity rule), so the rule validates.
  • Unit tests + a non-destructive live test (granting an already-present role hits the reject path with zero writes).

Hard PED limit (shapes the scope)

PED is add/modify-only for access control. DomainModels$AccessRule and DomainModels$MemberAccess can be added and their leaves set, but never removed — PED returns "Element of type 'DomainModels$AccessRule' cannot be removed. Do not try removing elements of this type again" (same for MemberAccess). Therefore:

  • AddEntityAccessRule for a role with no existing rule → works.
  • For a role that already has a rule → rejected (can't remove the old rule/members to replace it cleanly).
  • RemoveEntityAccessRule / RevokeEntityMemberAccessrejected with an actionable "do it in Studio Pro / use a local .mpr" message (not faked).

Follow-ups (not in this change)

  • In-place modify of an existing rule: feasible within the add/set-only limit (set leaves, set member accessRights, add missing members) but cannot prune stale members — so it's only a partial "replace". Decide whether a best-effort modify is worth it vs. the current clean reject.
  • Page allowed-roles (UpdateAllowedRoles) and microflow access ride on Pages$Page / Microflows$Microflow, which PED authors — likely reachable the same way; not yet probed/wired. (Note the separate page-access persistence bug GRANT VIEW ON PAGE reports success but does not persist page access (allowed roles stay empty; CE0557) #696.)
  • Capability model split into entity_access_rules (available), security_roles (sealed), integrations_settings (no path) in capabilities.yaml.

Related: #699 (navigation over MCP — same "unwired, not blocked" pattern).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions