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, includeDisabled 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)
- type ActivityReader
- type AgentReloader
- type AgentStore
- type AgentWriter
- type AssignmentStore
- type AssignmentWriter
- 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) Delete(ctx context.Context, authority authz.Authority, agentID 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) RemoveUser(ctx context.Context, authority authz.Authority, agentID, userID string) error
- func (m *Management) Update(ctx context.Context, authority authz.Authority, candidate config.Agent) (config.Agent, error)
- 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) Delete(ctx context.Context, authority authz.Authority, agentID string) (config.Agent, error)
- func (s *Service) ListReadable(ctx context.Context, authority authz.Authority, includeDisabled 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") )
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 applies both the collection list decision and a read decision to every candidate. 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 DB binding from that channel to this exact agent. Either mismatch fails closed; channel ID by itself is never an agent-use capability.
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 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, 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) 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) 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) 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. Non-admins cannot change scope; admins default an empty scope to system and reject any other value. The caller supplies a transport-validated candidate; reload is best-effort.
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) 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.