Skip to content

Agent capability ceiling: enforce agent caps ∩ owner caps in PermissionHelper #855

@chubes4

Description

@chubes4

Context

Phase 3 of agent runtime authentication (#740). Phase 1 (PR #853) added token CRUD. Phase 2 (#854) adds the auth middleware that resolves tokens → agent context.

This phase modifies PermissionHelper::can() to enforce the capability ceiling — an agent's effective capabilities are the intersection of its own granted capabilities and its owner's WordPress capabilities.

What to Build

inc/Abilities/PermissionHelper.php modifications

New static properties:

  • $acting_agent_id — the agent ID from the resolved token (null when no agent context)
  • $agent_capabilities — the token's capability restrictions (null = unrestricted)
  • $agent_owner_id — the owner's user ID (for ceiling checks)

New methods:

  • set_agent_context(int $agent_id, int $owner_id, ?array $capabilities) — called by AgentAuthMiddleware
  • clear_agent_context() — reset after request (or in try/finally)
  • get_acting_agent_id(): ?int — for callers that need to know if they're in agent context
  • in_agent_context(): bool — convenience check

Modify can($action):

Current flow:

  1. CLI bypass → true
  2. Action Scheduler bypass → true
  3. Pre-auth context → check authenticated_user_id caps or allow
  4. Standard → check current_user caps

New flow (insert between 3 and 4):

3.5. Agent context active?
     ├── Token has capability restrictions?
     │   ├── YES: Is this action in the token's capabilities list?
     │   │        ├── NO → deny (token doesn't grant this)
     │   │        └── YES → continue to owner ceiling check
     │   └── NO: unrestricted token → continue to owner ceiling check
     ├── Owner ceiling: does owner have this WP capability?
     │   ├── NO → deny (agent cannot exceed owner)
     │   └── YES → allow

Key principle: The capability ceiling is always enforced, even for unrestricted tokens. An agent owned by an Editor can never manage_options regardless of token configuration.

Per-token vs per-agent capabilities

Two levels of restriction:

  1. Per-agent (agent_config.tool_policy) — which tools the agent can use (already enforced by ToolPolicyResolver)
  2. Per-token (datamachine_agent_tokens.capabilities) — which WP capabilities this specific token grants

The token capabilities are a subset of the agent's capabilities, which are a subset of the owner's capabilities. Three nested ceilings:

owner WP capabilities (e.g., Editor)
  ∩ agent tool policy (e.g., content tools only)
    ∩ token capabilities (e.g., chat + use_tools only)
      = effective permissions

Depends On

Related

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