Skip to content

feat: Agent runtime token system — Phase 1 (token CRUD)#853

Merged
chubes4 merged 2 commits intomainfrom
feat/agent-runtime-tokens
Mar 18, 2026
Merged

feat: Agent runtime token system — Phase 1 (token CRUD)#853
chubes4 merged 2 commits intomainfrom
feat/agent-runtime-tokens

Conversation

@chubes4
Copy link
Member

@chubes4 chubes4 commented Mar 18, 2026

Summary

  • Adds per-agent bearer tokens for runtime authentication — the foundation for agent-level service accounts in WordPress
  • Phase 1 of issue Consider agent-level runtime authentication #740: token CRUD (create, revoke, list). Phase 2 (auth middleware + capability ceiling) will follow
  • 2 new files, 3 modified — 994 lines added

Why This Matters

This sets the foundation for "every user on a site can have their own AI agent":

WordPress User (human)
    │
    │  owns
    │
Agent (service account)
    ├── bearer token → Kimaki, CI, REST clients authenticate AS this agent
    ├── capability set → subset of owner's WP capabilities (Phase 2)
    ├── tool policy → which tools this agent can use (already built)
    └── scoped resources → pipelines, flows, jobs (already built)

Token Design

  • Format: datamachine_{agent_slug}_{64_random_hex_chars}
  • Storage: SHA-256 hash in DB (raw token returned once on creation, never stored)
  • Table: datamachine_agent_tokens with token_hash UNIQUE index for O(1) lookups
  • Features: labels, optional capability restrictions, optional expiry, last_used_at tracking

New Surfaces

CLI

# Create a token for an agent
wp datamachine agents token create chubes-bot --label="kimaki-prod"

# Create with 90-day expiry
wp datamachine agents token create chubes-bot --label="ci" --expires-in=7776000

# Create with restricted capabilities
wp datamachine agents token create chubes-bot --capabilities='["datamachine_chat"]'

# List tokens (metadata only — never shows the token value)
wp datamachine agents token list chubes-bot

# Revoke a token (immediate invalidation)
wp datamachine agents token revoke chubes-bot 3

REST API

Method Endpoint Description
POST /agents/{id}/tokens Create token
GET /agents/{id}/tokens List tokens
DELETE /agents/{id}/tokens/{token_id} Revoke token

Abilities

Ability Access Level
datamachine/create-agent-token Agent admin
datamachine/revoke-agent-token Agent admin
datamachine/list-agent-tokens Agent operator+

Phase 2 (Next PR)

  • AgentAuthMiddleware: hooks rest_authentication_errors, resolves bearer token → agent context
  • PermissionHelper::set_agent_context(): sets acting agent + capability ceiling
  • Capability ceiling enforcement: agent caps ∩ owner caps

Closes

Partially addresses #740 (Phase 1 of multi-phase implementation)

Add per-agent bearer tokens for runtime authentication. This is Phase 1
of the agent runtime auth system (issue #740) — token CRUD without the
auth middleware (Phase 2).

Database (AgentTokens.php):
- datamachine_agent_tokens table: token_id, agent_id, token_hash,
  token_prefix, label, capabilities, last_used_at, expires_at
- Tokens stored as SHA-256 hashes — raw token only returned on create
- Token format: datamachine_{agent_slug}_{64_hex_chars}
- create_token(), resolve_token(), revoke_token(), list_tokens()
- revoke_all_for_agent() for agent deletion cleanup
- touch_last_used() for activity tracking

Abilities (AgentTokenAbilities.php):
- datamachine/create-agent-token: validates agent exists/active,
  checks admin access, generates crypto-random token, returns raw
  token once with warning to save it
- datamachine/revoke-agent-token: admin access check, agent ownership
  validation, immediate invalidation
- datamachine/list-agent-tokens: operator+ access, returns metadata
  only (never token hashes)

CLI (AgentsCommand.php):
- wp datamachine agents token create <slug> --label=... --expires-in=...
- wp datamachine agents token list <slug>
- wp datamachine agents token revoke <slug> <token_id>
- Prominent warning on create: save the token, it cannot be retrieved

REST (Agents.php):
- POST /agents/{id}/tokens — create token
- GET /agents/{id}/tokens — list tokens
- DELETE /agents/{id}/tokens/{token_id} — revoke token
- All thin wrappers over AgentTokenAbilities

Bootstrap (data-machine.php):
- AgentTokens::create_table() in activation
- AgentTokenAbilities in abilities initialization

Phase 2 (separate PR) will add AgentAuthMiddleware that resolves
these tokens on incoming requests, sets agent context, and enforces
the capability ceiling.
@github-actions
Copy link

github-actions bot commented Mar 18, 2026

Homeboy Results — data-machine

Lint

⚡ Scope: changed files only

lint (changed files only)

Test

⚡ Scope: changed files only

test (changed files only)

Audit

⚡ Scope: changed files only

audit (changed files only)

Tooling versions
  • Homeboy CLI: homeboy 0.81.1+05cb2742
  • Extension: wordpress from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: unknown
  • Action: Extra-Chill/homeboy-action@v1

Homeboy Action v1

Add the runtime authentication layer that resolves agent bearer tokens
into scoped execution contexts with capability ceilings.

AgentAuthMiddleware (new file):
- Hooks rest_authentication_errors at priority 90
- Only intercepts Authorization: Bearer datamachine_* tokens
- hash(token) → AgentTokens::resolve_token() lookup
- Validates: token not expired, agent active, owner user exists
- wp_set_current_user(owner_id) — WP sees the owner for cap checks
- PermissionHelper::set_agent_context() — sets agent scoping layer
- Updates last_used_at on every successful auth
- Non-matching tokens pass through to WP's normal auth chain

PermissionHelper modifications:
- New static properties: acting_agent_id, agent_owner_id,
  agent_token_capabilities
- set_agent_context() / clear_agent_context() / get_acting_agent_id()
  / in_agent_context() — agent context lifecycle
- agent_can() — enforces capability ceiling:
  1. Token capability restrictions (if set, action must be in list)
  2. Owner WP capability check (ceiling — agent never exceeds owner)
- can() now checks agent context before pre-auth and standard paths
- acting_user_id() returns owner's user_id in agent context

Three nested permission ceilings:
  owner WP role (e.g., Editor)
    ∩ agent tool policy (ToolPolicyResolver, already built)
      ∩ token capabilities (per-token restrictions)
        = effective permissions

Closes #854, closes #855
@chubes4 chubes4 merged commit ace357b into main Mar 18, 2026
3 checks passed
@chubes4 chubes4 deleted the feat/agent-runtime-tokens branch March 18, 2026 19:03
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