Phase 4 operator platform

Scoped PAT management: permission strings, plaintext-once creation, IP restrictions, expiry, and revocation via gRPC to the Auth service — never direct DB access.

Milestone 4.A.4 — Token Management API

Status: Done Goal: Track A — Management API Server Phase: 4 — Operator Platform & Multi-Provider Estimated effort: 2 days Track: Track A — Management API Server


Why This Milestone Exists

Operators need a self-service surface for issuing, scoping, and revoking Personal Access Tokens (PATs). The API documentation already specifies the schema and permission model; this milestone wires those specifications into the management API. One critical invariant: the API server should never touch the token hash table directly — all revocation goes through AuthService.RevokeToken gRPC, mirroring the proxy's own "gRPC to auth, not direct DB" rule.


Non-Goals

  • OAuth/SSO session tokens (Phase 4.5)
  • Token rotation automation (future)
  • Batch token issuance

Orientation (indicative)

Named paths, package layouts, libraries, schemas, env vars, and commands anywhere on this page are rough sketches for orientation — inspiration and a baseline, not a required change list.

During implementation, expect to:

  • open the live tree and follow existing patterns before inventing new ones
  • research current constraints (latency, tenancy, deploy shape, libraries) more deeply than this page can
  • advance the design beyond the sketch where measurement or code reality says so
  • land work in different filenames, merged packages, deferred docs, or new surfaces when the situation calls for it

Prefer outcomes over matching any particular file tree or command sequence.

Areas that may be involved (situational — not a checklist):

  • Management API
  • Auth service
  • Database schema / migrations

Suggested naming (provisional)

Rename freely to match the change that actually lands.

  • Branch: feature/m4-a-4-token-management
  • PR title: feat(api): PAT management API with scoped permissions and gRPC revocation (m4.A.4)

Endpoints (illustrative)

Route shapes below are a planning sketch — names, nesting, and payloads may change during implementation.

GET /v1/tokens → CursorPage[TokenResponse] (org-scoped; plaintext never returned in list)
POST /v1/tokens → TokenCreateResponse (201; includes plaintext token — shown exactly once)
GET /v1/tokens/{token_id} → TokenResponse (no plaintext; via ListTokens filter)
DELETE /v1/tokens/{token_id} → 204 (revocation via AuthService.RevokeToken gRPC)

PATCH deferred.


Token Schema

Python
class TokenCreateRequest(BaseModel):
 name: str # human-readable label
 permissions: list[str] # ADR-0009 strings
 allowed_ips: list[str] | None = None # CIDR syntax only; not persisted
 expires_at: datetime | None = None
 agent_id: UUID | None = None

class TokenCreateResponse(BaseModel):
 id: UUID
 name: str
 token: str # plaintext — shown once
 permissions: list[str]
 prefix: str
 expires_at: datetime | None
 created_at: datetime

class TokenResponse(BaseModel):
 id: UUID
 name: str
 permissions: list[str]
 prefix: str
 expires_at: datetime | None
 created_at: datetime
 revoked_at: datetime | None
 is_revoked: bool

Permission Strings

Scoped permission strings map to the existing 64-bit permission bitmap (ADR-0009):

Permission StringBitmap BitDescription
memory:readbit 0Read memories
memory:writebit 1Create/update memories
memory:deletebit 2Delete memories
session:createbit 16Start proxy sessions
admin:user_managebit 32Manage users
admin:org_managebit 35Org settings (alias OrgSettingsWrite)
admin:token_createbit 36Issue tokens
admin:token_revokebit 37Revoke tokens

Full catalog is in API_DOCUMENTATION.md Permissions Reference and app/permissions_codec.py.


Business Rules

  • Plaintext shown exactly once: on POST, Auth generates/hashes (Argon2id) and returns plaintext once.
  • Revocation via gRPC only: DELETE calls AuthService.RevokeToken — never direct token-table writes.
  • IP restriction validation: allowed_ips CIDRs validated syntactically; not stored (follow-up for persistence).
  • Permission scope enforcement: caller cannot grant permissions they do not hold → 403 PERMISSION_ELEVATION_DENIED.

Success signals

Outcome-oriented signals that the milestone is in good shape. Exact filenames, package layouts, and commands may differ from any sketches above.

  • Plaintext token present in create response, absent in all list/get responses
  • Token revocation reflected in proxy auth-cache within 5s (SEC7_2b; RevokeToken gRPC path)
  • Permission elevation attempt returns 403 PERMISSION_ELEVATION_DENIED
  • Invalid CIDR in allowed_ips returns VALIDATION_ERROR (HTTP 400 per apierror)
  • TestAPI_ISO_TOKEN_*: org A cannot read/revoke org B's tokens (404)

Prerequisites

  • M4.A.1 skeleton merged
  • AuthService.RevokeToken gRPC available
Edit on GitHub

Last updated on