Skip to content

Auth and identity

foxctl’s auth and identity system handles authentication, authorization, token brokerage, and identity propagation across CLI, web, and adapter surfaces. This page describes the current model, known boundaries, and security invariants.

flowchart TD
Adapters[chat adapters + web handlers]
Identity[domain/identity]
Auth[auth / Casbin]
Hooks[hook policy runner]
Broker[authbroker]
OAuth[web OAuth callback]
Verify[verification / CoVe]
Adapters --> Identity
Identity --> Auth
Identity --> Hooks
Identity --> Broker
OAuth --> Broker
Adapters --> Verify
PackageResponsibilityPrimary types/functions
internal/domain/identityCanonical principal model + context propagationPrincipal, Subject(), ConversationKey(), WithPrincipal, FromContext
internal/authCasbin authorization for HTTP and hook/tool resourcesNewEnforcer, Enforce, Middleware, PolicyHookRunner
internal/auth/brokerOAuth token/auth-request lifecycle and encrypted persistenceBroker, Store, TokenRow, AuthRequestRow, Encrypt/Decrypt, OpenSQLite/OpenPostgres
internal/intelligence/verificationChain-of-Verification (baseline → claims → parallel verify → refine)CoVe, Spawner, CoVeRequest, CoVeResponse

Identity travels through request and runtime boundaries via a single principal carrier:

  1. Adapter or handler constructs identity.Principal with Platform, UserID, and tenant/actor fields when available.
  2. Principal is attached to context.Context via identity.WithPrincipal.
  3. Authorization and hook logic reads from the same context via identity.FromContext.
  4. Conversation and session routing uses Principal.ConversationKey(...) for tenant-aware keys.

This contract keeps identity consistent across chat adapters, web handlers, hooks, and tool execution. There is no secondary identity channel — the principal in context is the single source of truth.

The authorization layer uses an embedded Casbin model with a CSV adapter.

ItemCurrent behavior
Enforcer backendEmbedded Casbin model + CSV adapter (NewEnforcer)
Subject mappingPrincipal.Subject() — formats as user:<platform>:<id> or actor:<id>
Tenant mappingEmpty tenant maps to * domain
HTTP middleware resourceapi:<path> with read/write action derived from HTTP method
Hook policy resourcetool:<name> with execute action
Fallback modeNil enforcer and anonymous principals pass through

Casbin policies use stable resource and action prefixes:

  • api:* for HTTP routes, with actions read and write
  • tool:* for hook and tool resources, with action execute

This naming is durable and auditable. Changes to resource or action strings require policy migration.

NewPostgresEnforcer is currently a placeholder and returns not-implemented. The production enforcer uses the embedded model + CSV adapter.

The auth broker (internal/auth/broker) manages OAuth token lifecycle and encrypted persistence.

AreaCurrent behavior
Provider abstractionmicrosoft_graph, google, github via Provider enum
Token keying(tenant_id, subject, provider, scopes_hash)
Scope normalizationScopesHash(scopes, audience) sorts scopes before hashing
EncryptionAES-256-GCM via Encrypt/Decrypt; key must be 32 bytes
Storage backendsSQLite and Postgres implementations of Store
CleanupExpired token and auth-request delete APIs

The /api/oauth/callback handler exists but is currently stubbed — it is not yet wired to Broker.CompleteAuth. This is a documented TODO, not a hidden gap.

internal/intelligence/verification is identity-adjacent, not identity-owning. It implements Chain-of-Verification (CoVe) for claim checking:

StageFunction
Baseline generationDraft initial answer
Claim extractionParse verifiable claims
Parallel verificationWorker pool checks each claim
RefinementProduces corrected final answer

Primary integration surface: skills/cove_verify (verification/cove_verify).

Verification is an explicit opt-in workflow. It does not run automatically on every response and does not introduce hidden policy side effects.

InvariantWhy it matters
Principal is the single identity carrier across layersAvoids subject drift between adapters, middleware, and hooks
Resource/action naming is stable (api:*, tool:*)Keeps Casbin policy durable and auditable
OAuth blobs are encrypted at restReduces token disclosure risk
Tenant-aware conversation keysPrevents cross-tenant key collisions
Verification is explicit opt-in workflow logicAvoids hidden policy side effects

All routes that modify state enforce principal propagation through the auth middleware. The middleware:

  1. Extracts or constructs a Principal from the request
  2. Attaches it to the request context
  3. Evaluates Casbin policy for the requested resource and action
  4. Allows or denies based on the enforcer result

See API server for the full route surface and Protocol v1 for envelope shapes.