Documentation
¶
Overview ¶
Package access is the policy-enforcement point for Agent resources.
Index ¶
- Variables
- func GroupAgentAuthority(groupID, agentID string) (authz.Authority, error)
- func SystemAgentAuthority(component string) (authz.Authority, error)
- func WorkerAgentAuthority(ownerID, agentID string) (authz.Authority, error)
- type Access
- func (a *Access) CanCreate() error
- func (a *Access) CanList() error
- func (a *Access) CanUse(ctx context.Context, agentID string) (bool, error)
- func (a *Access) Delete(ctx context.Context, agentID string) (config.Agent, error)
- func (a *Access) ListReadable(ctx context.Context, deploymentWide bool) ([]config.Agent, error)
- func (a *Access) Manage(ctx context.Context, agentID string) (config.Agent, error)
- func (a *Access) Read(ctx context.Context, agentID string) (config.Agent, error)
- func (a *Access) Use(ctx context.Context, agentID string) (config.Agent, error)
- func (a *Access) UseDedicated(ctx context.Context, agentID, channelID string) (config.Agent, error)
- func (a *Access) UseDedicatedForType(ctx context.Context, agentID, channelID, channelType string) (config.Agent, error)
- type ActivityReader
- type AgentReloader
- type AgentStore
- type AgentWriter
- type AssignmentStore
- type AssignmentWriter
- type CredentialWriter
- type Management
- func (m *Management) AssignUser(ctx context.Context, authority authz.Authority, agentID, userID string) (UserRef, error)
- func (m *Management) Create(ctx context.Context, authority authz.Authority, candidate config.Agent) (config.Agent, error)
- func (m *Management) CreateWithProviderCredentials(ctx context.Context, authority authz.Authority, candidate config.Agent, ...) (config.Agent, error)
- func (m *Management) Delete(ctx context.Context, authority authz.Authority, agentID string) error
- func (m *Management) DeleteProviderCredential(ctx context.Context, authority authz.Authority, agentID, providerID string) error
- func (m *Management) ListAgentLastActive(ctx context.Context, userID string) (map[string]time.Time, error)
- func (m *Management) ListAssignedUsers(ctx context.Context, authority authz.Authority, agentID string) ([]UserRef, error)
- func (m *Management) ListProviderCredentials(ctx context.Context, authority authz.Authority, agentID string) ([]providercred.Metadata, error)
- func (m *Management) RemoveUser(ctx context.Context, authority authz.Authority, agentID, userID string) error
- func (m *Management) SetProviderCredential(ctx context.Context, authority authz.Authority, agentID string, ...) (providercred.Metadata, error)
- func (m *Management) Update(ctx context.Context, authority authz.Authority, candidate config.Agent) (config.Agent, error)
- type ProviderReader
- type Service
- func (s *Service) Authorize(ctx context.Context, authority authz.Authority, agentID string, ...) error
- func (s *Service) AuthorizeViaChannelBinding(ctx context.Context, authority authz.Authority, agentID string) error
- func (s *Service) Begin(_ context.Context, authority authz.Authority) (*Access, error)
- func (s *Service) CanCreate(ctx context.Context, authority authz.Authority) error
- func (s *Service) CanList(ctx context.Context, authority authz.Authority) error
- func (s *Service) CanUseAsUser(ctx context.Context, userID, agentID string) (bool, error)
- func (s *Service) Delete(ctx context.Context, authority authz.Authority, agentID string) (config.Agent, error)
- func (s *Service) ListReadable(ctx context.Context, authority authz.Authority, deploymentWide bool) ([]config.Agent, error)
- func (s *Service) Manage(ctx context.Context, authority authz.Authority, agentID string) (config.Agent, error)
- func (s *Service) Read(ctx context.Context, authority authz.Authority, agentID string) (config.Agent, error)
- func (s *Service) Use(ctx context.Context, authority authz.Authority, agentID string) (config.Agent, error)
- type UserDirectory
- type UserRef
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidScope reports an admin-supplied scope that is neither system nor // restricted. It is a validation error (400), never an authorization denial. ErrInvalidScope = errors.New("agent scope must be 'system' or 'restricted'") // ErrUserNotFound reports an assignment target that does not exist. ErrUserNotFound = errors.New("assignment target user not found") // ErrInUse reports that a durable resource still references the Agent. ErrInUse = errors.New("agent is still in use") // ErrUnknownProvider reports a credential input whose provider_id is not an // existing canonical Provider (an alias or an unconfigured ID). It is a // validation error (400), raised before any encryption. ErrUnknownProvider = errors.New("provider credential targets an unknown or non-canonical provider") ErrCredentialsUnavailable = errors.New("agent provider credentials are unavailable") )
Management-specific typed errors. Authorization/availability reuse the Service sentinels (ErrForbidden / ErrNotFound / ErrUnavailable) so the transport maps every Agent error through one vocabulary.
var ( ErrForbidden = errors.New("agent access forbidden") ErrNotFound = errors.New("agent not found") )
Functions ¶
func GroupAgentAuthority ¶
GroupAgentAuthority mints an exact group/agent authority for one group turn. A triggering user is intentionally absent from this capability, so a group turn can never reach user-private access.
func SystemAgentAuthority ¶
SystemAgentAuthority mints the named maintenance authority used for an agent invocation. System execution is a named component; it never inherits an admin or user identity.
Types ¶
type Access ¶
type Access struct {
// contains filtered or unexported fields
}
Access captures one validated authority and caches its assignment relation for the duration of a multi-step use case.
func (*Access) ListReadable ¶
ListReadable returns the caller's own fleet: the agents they can actually use, plus the ones they created whatever state those are in.
deploymentWide is the admin's separate, explicit ask for everyone's agents. Without it an admin gets the same personal fleet as anyone else — being able to reach every agent is not a reason to be shown every agent, and the pages that browse your own agents should not turn into a directory of everybody's on one account. SQL may narrow candidates for performance, but never decides visibility.
func (*Access) UseDedicated ¶
UseDedicated requires both the authority's exact held channel binding and a current enabled DB binding from that channel to this exact agent. Either mismatch fails closed; channel ID by itself is never an agent-use capability.
func (*Access) UseDedicatedForType ¶ added in v0.63.0
func (a *Access) UseDedicatedForType(ctx context.Context, agentID, channelID, channelType string) (config.Agent, error)
UseDedicatedForType additionally requires the current channel type to match the platform that minted the queued chat. This prevents a channel record that was reconfigured for another platform from authorizing stale queued work.
type ActivityReader ¶
type ActivityReader interface {
ListAgentLastActive(ctx context.Context, userID string) (map[string]time.Time, error)
}
ActivityReader is the conversation-activity read model: the last-active time per agent for one user's own conversations.
type AgentReloader ¶
AgentReloader refreshes an agent's runtime state after a durable change. agent.PoolManager.SyncAgent satisfies it. Reload is eventually-consistent, so Management treats a failure as best-effort (see Create/Update/Delete).
type AgentStore ¶
type AgentStore interface {
GetAgent(ctx context.Context, id string) (config.Agent, error)
ListAgents(ctx context.Context) ([]config.Agent, error)
}
AgentStore is deliberately narrow, but includes list because collection filtering belongs at the PEP rather than in transports or SQL.
type AgentWriter ¶
type AgentWriter interface {
GetAgent(ctx context.Context, id string) (config.Agent, error)
CreateAgent(ctx context.Context, a config.Agent) error
UpdateAgent(ctx context.Context, a config.Agent) error
DeleteAgent(ctx context.Context, id string) error
}
AgentWriter persists agent rows. config.Store satisfies it; the interface stays narrow so Management cannot reach unrelated aggregate config.
type AssignmentStore ¶
type AssignmentWriter ¶
type AssignmentWriter interface {
AssignAgent(ctx context.Context, userID, agentID string) error
RemoveAgent(ctx context.Context, userID, agentID string) error
ListAgentUserIDs(ctx context.Context, agentID string) ([]string, error)
}
AssignmentWriter mutates and lists the user<->agent assignment relation. auth.AuthStore satisfies it.
type CredentialWriter ¶ added in v0.61.0
type CredentialWriter interface {
List(ctx context.Context, agentID string) ([]providercred.Metadata, error)
Set(ctx context.Context, agentID string, input providercred.Input) (providercred.Metadata, error)
Delete(ctx context.Context, agentID, providerID string) error
CreateAgentWithCredentials(ctx context.Context, agent config.Agent, inputs []providercred.Input) error
}
CredentialWriter is the Agent Provider credential encryption/persistence boundary. *providercred.Service satisfies it. Management authorizes and validates before delegating; it never sees plaintext after handing off.
type Management ¶
type Management struct {
// contains filtered or unexported fields
}
Management owns the Agent write use cases: create/update/delete, admin user assignment, and the conversation-activity read model. Every method authorizes through the Agent PEP (Service) before any durable read or write, then performs the persistence, cross-write compensation, and best-effort runtime reload the HTTP transport used to orchestrate itself. Splitting these off the read-only Service keeps the PEP's decision surface narrow while giving the Agent domain a single owner for its mutating invariants (unique ID, creator auto-assignment atomicity, scope rules).
func NewManagement ¶
func NewManagement(pep *Service, agents AgentWriter, assign AssignmentWriter, reloader AgentReloader, users UserDirectory, activity ActivityReader, creds CredentialWriter, providers ProviderReader, log *slog.Logger) *Management
NewManagement builds the Agent management service over the Agent PEP and its write/reload/lookup ports. log defaults to slog.Default() when nil.
func (*Management) AssignUser ¶
func (m *Management) AssignUser(ctx context.Context, authority authz.Authority, agentID, userID string) (UserRef, error)
AssignUser assigns a user to an agent. Admin-only. It verifies the agent then the user exists (preserving the historical 404 order) before writing.
func (*Management) Create ¶
func (m *Management) Create(ctx context.Context, authority authz.Authority, candidate config.Agent) (config.Agent, error)
Create authorizes and persists a new agent, enforcing the scope rules, generating a unique ID, and — for a restricted agent a non-admin creates — auto-assigning the creator. The create+auto-assign pair is atomic from the caller's view: a failed assignment compensates by deleting the just-created agent, so a restricted agent is never left invisible to its creator. The caller supplies a fully transport-validated candidate whose ID is the base slug; Management owns the scope decision, uniqueness, workspace, and creator.
func (*Management) CreateWithProviderCredentials ¶ added in v0.61.0
func (m *Management) CreateWithProviderCredentials(ctx context.Context, authority authz.Authority, candidate config.Agent, inputs []providercred.Input) (config.Agent, error)
CreateWithProviderCredentials creates an Agent together with per-Provider key overrides in one atomic persist. It shares Create's authorization, scope, and auto-assign compensation, adding canonical-Provider validation and encryption before the composite write. An empty inputs slice is equivalent to Create.
func (*Management) DeleteProviderCredential ¶ added in v0.61.0
func (m *Management) DeleteProviderCredential(ctx context.Context, authority authz.Authority, agentID, providerID string) error
DeleteProviderCredential removes an Agent Provider key override, restoring the global-key fallback. It requires Manage, is idempotent, and reloads only the affected Agent's runners after commit.
func (*Management) ListAgentLastActive ¶
func (m *Management) ListAgentLastActive(ctx context.Context, userID string) (map[string]time.Time, error)
ListAgentLastActive returns the last-active time per agent for the given user's own conversations. It carries no additional authorization: the caller has already been list-authorized for the agents it enriches, and the read is scoped to that same user's activity.
func (*Management) ListAssignedUsers ¶
func (m *Management) ListAssignedUsers(ctx context.Context, authority authz.Authority, agentID string) ([]UserRef, error)
ListAssignedUsers returns the account references for the users assigned to an agent. Admin-only: the gate runs before any durable read.
func (*Management) ListProviderCredentials ¶ added in v0.61.0
func (m *Management) ListProviderCredentials(ctx context.Context, authority authz.Authority, agentID string) ([]providercred.Metadata, error)
ListProviderCredentials returns secret-free credential metadata for an Agent. Read access is sufficient; only Set/Delete require Manage.
func (*Management) RemoveUser ¶
func (m *Management) RemoveUser(ctx context.Context, authority authz.Authority, agentID, userID string) error
RemoveUser unassigns a user from an agent. Admin-only.
func (*Management) SetProviderCredential ¶ added in v0.61.0
func (m *Management) SetProviderCredential(ctx context.Context, authority authz.Authority, agentID string, input providercred.Input) (providercred.Metadata, error)
SetProviderCredential upserts (or rotates) one Agent Provider key override. It requires Manage, validates the target is a canonical configured Provider before any encryption, and reloads only the affected Agent's runners after commit.
func (*Management) Update ¶
func (m *Management) Update(ctx context.Context, authority authz.Authority, candidate config.Agent) (config.Agent, error)
Update authorizes (Manage) and persists an agent edit. Scope is the agent's reach — system means every user may use it, restricted means only assigned users — and its manager decides it: an admin for any agent, the creator for their own. An empty scope keeps the persisted one for a creator and defaults to system for an admin (the historical create-shaped default); any other value is rejected. The caller supplies a transport-validated candidate; reload is best-effort.
type ProviderReader ¶ added in v0.61.0
ProviderReader lists only canonical Provider IDs so Management can reject an alias or unconfigured Provider before encryption without reading global Provider config or its API key.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func NewService(agents AgentStore, assign AssignmentStore) *Service
func (*Service) Authorize ¶
func (s *Service) Authorize(ctx context.Context, authority authz.Authority, agentID string, action authz.Action) error
Authorize is the narrow cross-domain Agent port. It reads the durable Agent and applies the same direct Agent rules as the public access methods; a dedicated-channel binding is intentionally not inferred here.
func (*Service) AuthorizeViaChannelBinding ¶
func (s *Service) AuthorizeViaChannelBinding(ctx context.Context, authority authz.Authority, agentID string) error
AuthorizeViaChannelBinding authorizes read/execute of agentID for a trusted dedicated-channel Authority: the exact held channel binding whose CURRENT persisted channel→agent binding names this exact agent. It is the Agent PEP's sole interpretation of a dedicated channel, so cross-domain callers (the session flow's Agent gate) never re-derive channel bindings themselves. A held binding alone is never authority for an arbitrary agent; every mismatch fails closed.
func (*Service) CanUseAsUser ¶ added in v0.61.0
CanUseAsUser evaluates one ordinary, non-admin user's current execute access. It is intended for trusted adapters validating a durable delegation before persisting it; callers receive only the decision, never a minted Authority.
func (*Service) ListReadable ¶
type UserDirectory ¶
type UserDirectory interface {
LookupUser(ctx context.Context, userID string) (UserRef, error)
LookupUsers(ctx context.Context, userIDs []string) ([]UserRef, error)
}
UserDirectory resolves assignment-target account display data. The composition root backs it with the account user store; LookupUsers skips IDs that no longer resolve so a stale assignment link never breaks the admin listing.