Overview
Not every permission maps to an OAuth provider scope. Organizations define internal operations with their own names (e.g., acme:gliding, pipeline:trigger, reports:generate). These should be first-class citizens in the authorization system, not workarounds.
Problem
- All current scope enforcement assumes an underlying OAuth provider connection
- Internal business operations have no native representation in Nexus
- Teams build custom scope registries per-project to fill this gap
Proposed Solution
Custom scopes are declared when registering an agent — no separate scope registry is required. The agent's allowed_scopes list is the source of truth.
Behavior difference by scope type
| Scope type |
Example |
Broker behavior |
| Provider scope |
crm:contacts:read |
Fetches the underlying OAuth token from the stored connection, returns it scoped to the requested permissions |
| Custom scope |
acme:gliding |
Returns a signed session token asserting the agent is authorized for this scope |
Custom scope session response
{
"session_id": "sess_xyz",
"session_token": "eyJ...",
"scopes_granted": ["acme:gliding"],
"expires_at": "2025-05-11T21:00:00Z",
"token_type": "session"
}
The downstream service verifies the session token either via broker's public key or by calling GET /v1/agent-sessions/{id}.
Example registration
curl -X POST http://localhost:8080/admin/v1/agents \
-H "X-API-Key: $API_KEY" \
-d '{
"agent_id": "ops-agent",
"allowed_scopes": ["acme:gliding", "acme:flaring", "crm:contacts:read"]
}'
Acceptance Criteria
Priority
P3 — Small effort (builds on P1 agent session infrastructure)
Reference
AGENT_AUTH_PROPOSAL.md — Proposal 3
Overview
Not every permission maps to an OAuth provider scope. Organizations define internal operations with their own names (e.g.,
acme:gliding,pipeline:trigger,reports:generate). These should be first-class citizens in the authorization system, not workarounds.Problem
Proposed Solution
Custom scopes are declared when registering an agent — no separate scope registry is required. The agent's
allowed_scopeslist is the source of truth.Behavior difference by scope type
crm:contacts:readacme:glidingCustom scope session response
{ "session_id": "sess_xyz", "session_token": "eyJ...", "scopes_granted": ["acme:gliding"], "expires_at": "2025-05-11T21:00:00Z", "token_type": "session" }The downstream service verifies the session token either via broker's public key or by calling
GET /v1/agent-sessions/{id}.Example registration
Acceptance Criteria
session_token(not an OAuthaccess_token)token_type: "session"field differentiates the response from a standard OAuth token responseSTATE_KEYor a dedicated signing key)Priority
P3 — Small effort (builds on P1 agent session infrastructure)
Reference
AGENT_AUTH_PROPOSAL.md — Proposal 3