Skip to content

feat(auth): grant/revoke/list-users agent access abilities over WP_Agent_Access_Store - #538

Merged
chubes4 merged 1 commit into
Automattic:mainfrom
chubes4:feat/537-agent-access-write-abilities
Sep 8, 2026
Merged

feat(auth): grant/revoke/list-users agent access abilities over WP_Agent_Access_Store#538
chubes4 merged 1 commit into
Automattic:mainfrom
chubes4:feat/537-agent-access-write-abilities

Conversation

@chubes4

@chubes4 chubes4 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Closes #537.

What

Registers three write-side agent-access abilities in src/Auth/register-agent-access-abilities.php, over the existing WP_Agent_Access_Store contract (same file and style as the existing read-side pair):

Ability Permission gate Input Output Annotations
agents/grant-agent-access admin role on target agent { agent, user_id, role? (default viewer), workspace_id?, metadata? } { granted: true, grant: {...} } idempotent — the store contract upserts ("Create or update a grant")
agents/revoke-agent-access admin role on target agent { agent, user_id, workspace_id? } { revoked: bool } destructive
agents/list-agent-users operator role on target agent { agent, workspace_id? } { users: [grant] } idempotent, readonly

All three are show_in_rest: true, category agents-api, registered behind the same wp_has_ability guards as the read side.

Permission model

Agent-role, not WordPress capabilities — agent-role grants are the substrate's authorization model, so no capability checks are invented. Write abilities require the current principal to hold an admin role grant on the target agent (WP_Agent_Access::can_current_principal_access_agent( , ROLE_ADMIN, )); agents/list-agent-users requires operator. Both decisions run through the existing agents_access_permission filter hook so hosts can tighten or widen them exactly as they can for the read abilities.

Error surface

Execute callbacks return WP_Error (not success:false arrays): agents_access_invalid_agent, agents_access_unknown_agent (via a cheap WP_Agents_Registry::is_registered() lookup), agents_access_invalid_user, agents_access_invalid_role, agents_access_store_missing (when WP_Agent_Access::get_store() resolves to null), and agents_access_last_admin — revocation checks get_users_for_agent() first and refuses to remove the agent's last remaining admin grant (audience admin grants count toward the survivor set). The last-admin rule is documented in the ability description.

Consumer

Data Machine already implements WP_Agent_Access_Store via its AgentAccessStoreAdapter (Extra-Chill/data-machine#3473, interim datamachine/manage-agent-access ability) and will switch to these slugs once merged — retiring that plugin-side wrapper is the motivating use case from the issue.

Tests

  • New tests/agents-access-write-ability-smoke.php (33 assertions, registered in composer.json scripts.smoke): grant → list shows it → revoke → list empty; re-grant upserts instead of duplicating; non-admin principal denied on the grant permission gate; operator passes the listing gate; last-admin revoke refused with agents_access_last_admin; revoking a non-admin grant never blocked; workspace scoping; invalid role / invalid user / unknown agent / missing store WP_Errors; ability registration.
  • Full composer test (102 smoke files) and composer phpstan (level max) pass locally; Generic.Formatting.MultipleStatementAlignment clean on changed files.

Docs

docs/auth-consent-context-memory.md gains an "Agent access abilities" subsection documenting all five access ability slugs with permission gates, input/output, and annotations.

AI-generated with Claude Code via Homeboy worktree

@chubes4
chubes4 merged commit 5cb463c into Automattic:main Sep 8, 2026
4 checks passed
chubes4 pushed a commit to Extra-Chill/data-machine that referenced this pull request Sep 8, 2026
…ugh agents-api abilities

Automattic/agents-api#538 shipped agents/grant-agent-access, revoke-agent-access,
and list-agent-users over WP_Agent_Access_Store, which Data Machine already
implements via AgentAccessStoreAdapter. The admin Access panel now calls those
slugs (keyed by agent slug, per the registry) and enriches grants with WP user
display fields client-side via /wp/v2/users. executeAbility() accepts a
qualified slug so non-datamachine namespaces work without a second helper.

Reverts the out-of-scope AgentsCommand/AgentAccess touches from the previous
fixup; they dragged 28 pre-existing smoke-stub PHPStan findings (#3474) into
changed-file scope.
chubes4 added a commit to Extra-Chill/data-machine that referenced this pull request Sep 8, 2026
…s/v1 and delete Agents.php; access via agents-api abilities (#3473)

* refactor(api): tranche 4 — migrate Agents admin calls to /wp-abilities/v1 and delete wrapper routes

* fix: address tranche 4 CI findings — GET transport for readonly get-agent, owner default contract test, PHPStan stub ignores

* fix: pin logged-out owner contract to agent_owner_unresolved and cast access grant rows for static analysis

* refactor(api): keep agent-access routes pending agents-api#537; drop interim manage-agent-access ability

The write side of agent access belongs in the Agents API substrate, not
patched over from Data Machine. Automattic/agents-api#537 adds
agents/grant-agent-access, revoke-agent-access, and list-agent-users; until
that lands the three datamachine/v1 access routes stay and the admin keeps
calling them. Every other Agents route is deleted as planned.

* fix: keep Api\Agents registered for the retained access routes

* fix: restore access-route helper, correct grant/prune return types, baseline smoke-stub shadowing of WP_Agent_Access_Grant

* refactor(api): delete Agents.php entirely — access grants now go through agents-api abilities

Automattic/agents-api#538 shipped agents/grant-agent-access, revoke-agent-access,
and list-agent-users over WP_Agent_Access_Store, which Data Machine already
implements via AgentAccessStoreAdapter. The admin Access panel now calls those
slugs (keyed by agent slug, per the registry) and enriches grants with WP user
display fields client-side via /wp/v2/users. executeAbility() accepts a
qualified slug so non-datamachine namespaces work without a second helper.

Reverts the out-of-scope AgentsCommand/AgentAccess touches from the previous
fixup; they dragged 28 pre-existing smoke-stub PHPStan findings (#3474) into
changed-file scope.

* fix: pruneAgents return type, CLI WP_Error handling, eslint dependency-group and unused catch binding

* chore: baseline WP_Agent_Access_Grant smoke-stub shadowing for AgentsCommand (#3474)

* fix: dependency-group ordering in agents.js; correct get_users_for_agent return type to grant objects

* revert: leave AgentAccess.php untouched — docblock fix belongs with #3474

* chore: baseline grant-as-array PHPStan findings in AgentsCommand pending #3474

* test: dedupe revoke-token input in agents REST contract test

---------

Co-authored-by: homeboy-ci[bot] <266378653+homeboy-ci[bot]@users.noreply.github.com>
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.

Expose grant/revoke agent access as abilities

1 participant