Documentation
¶
Overview ¶
Package principal provides the core principal abstraction for identity management. A Principal is a unified identity root that can represent different types of actors: Human (interactive users), Application (OAuth clients), Agent (AI assistants), or Service (backend systems).
Index ¶
- Variables
- type AfterCommit
- type Agent
- type AppType
- type Application
- type Capabilities
- type CreateAgentInput
- type CreateApplicationInput
- type CreateHumanInput
- type CreateServiceInput
- type DefaultService
- func (s *DefaultService) CreateAgent(ctx context.Context, input CreateAgentInput) (*Principal, error)
- func (s *DefaultService) CreateApplication(ctx context.Context, input CreateApplicationInput) (*Principal, error)
- func (s *DefaultService) CreateHuman(ctx context.Context, input CreateHumanInput) (*Principal, error)
- func (s *DefaultService) CreateHumanInTx(ctx context.Context, tx *ent.Tx, input CreateHumanInput) (*Principal, AfterCommit, error)
- func (s *DefaultService) CreateService(ctx context.Context, input CreateServiceInput) (*Principal, error)
- func (s *DefaultService) Deactivate(ctx context.Context, id uuid.UUID) error
- func (s *DefaultService) GetByID(ctx context.Context, id uuid.UUID) (*Principal, error)
- func (s *DefaultService) GetByIdentifier(ctx context.Context, identifier string) (*Principal, error)
- func (s *DefaultService) MarkEmailVerified(ctx context.Context, id uuid.UUID) error
- func (s *DefaultService) Reactivate(ctx context.Context, id uuid.UUID) error
- func (s *DefaultService) Update(ctx context.Context, id uuid.UUID, input UpdateInput) (*Principal, error)
- func (s *DefaultService) UpdateAgent(ctx context.Context, id uuid.UUID, input UpdateAgentInput) (*Principal, error)
- func (s *DefaultService) UpdateApplication(ctx context.Context, id uuid.UUID, input UpdateApplicationInput) (*Principal, error)
- func (s *DefaultService) UpdateHuman(ctx context.Context, id uuid.UUID, input UpdateHumanInput) (*Principal, error)
- func (s *DefaultService) UpdateLastLogin(ctx context.Context, id uuid.UUID) error
- func (s *DefaultService) UpdateService(ctx context.Context, id uuid.UUID, input UpdateServiceInput) (*Principal, error)
- type Human
- type HumanTxCreator
- type Principal
- type Repository
- type Service
- type ServiceData
- type ServiceOption
- type Type
- type UpdateAgentInput
- type UpdateApplicationInput
- type UpdateHumanInput
- type UpdateInput
- type UpdateServiceInput
Constants ¶
This section is empty.
Variables ¶
var ErrEmailRequired = errors.New("principal: email is required")
ErrEmailRequired is returned when creating a human principal without an email. Only managed principals may omit one (ADR-005).
var ErrInvalidDelegator = errors.New("principal: delegating principal must exist and be active")
ErrInvalidDelegator is returned when an agent's delegating principal does not exist or is not active.
var ErrNotFound = errors.New("principal: not found")
ErrNotFound is returned for an unknown principal.
var ErrWrongType = errors.New("principal: wrong principal type")
ErrWrongType is returned when an operation for one principal type is applied to a principal of another.
Functions ¶
This section is empty.
Types ¶
type AfterCommit ¶ added in v0.14.0
AfterCommit registers a created entity with the authorization backend. It must be called only after the transaction that created the entity committed, and never when it rolled back.
type Agent ¶
type Agent struct {
ModelID string `json:"model_id"`
Version string `json:"version,omitempty"`
DelegatingPrincipalID *uuid.UUID `json:"delegating_principal_id,omitempty"`
CapabilityConstraints []string `json:"capability_constraints,omitempty"`
ResourceConstraints []string `json:"resource_constraints,omitempty"`
MaxTokenLifetimeSeconds int `json:"max_token_lifetime_seconds,omitempty"`
SessionID *string `json:"session_id,omitempty"`
RequiresConfirmation bool `json:"requires_confirmation"`
}
Agent represents AI agent-specific principal data.
type AppType ¶
type AppType string
AppType represents the type of OAuth application.
const ( // AppTypeWeb is a confidential web application. AppTypeWeb AppType = "web" // AppTypeSPA is a single-page application (public client). AppTypeSPA AppType = "spa" // AppTypeNative is a native mobile/desktop application. AppTypeNative AppType = "native" // AppTypeMachine is a machine-to-machine application. AppTypeMachine AppType = "machine" )
type Application ¶
type Application struct {
ClientID string `json:"client_id"`
AppType AppType `json:"app_type"`
RedirectURIs []string `json:"redirect_uris"`
AllowedGrants []string `json:"allowed_grants"`
AllowedResponseTypes []string `json:"allowed_response_types,omitempty"`
AccessTokenTTLSeconds int `json:"access_token_ttl_seconds"`
RefreshTokenTTLSeconds int `json:"refresh_token_ttl_seconds"`
RefreshTokenRotation bool `json:"refresh_token_rotation"`
FirstParty bool `json:"first_party"`
Public bool `json:"public"`
LogoURL *string `json:"logo_url,omitempty"`
Description *string `json:"description,omitempty"`
}
Application represents OAuth application-specific principal data.
type Capabilities ¶
type Capabilities struct {
CanAccessUI bool `json:"can_access_ui"`
CanManageProfile bool `json:"can_manage_profile"`
CanActOnBehalf bool `json:"can_act_on_behalf"`
CanDelegate bool `json:"can_delegate"`
RequiresApproval bool `json:"requires_approval"`
CanBypassRLS bool `json:"can_bypass_rls"`
CanRequestOffline bool `json:"can_request_offline"`
}
Capabilities represents what a principal is allowed to do.
func DefaultCapabilitiesForType ¶
func DefaultCapabilitiesForType(t Type) Capabilities
DefaultCapabilitiesForType returns the default capabilities for a principal type.
func ManagedHumanCapabilities ¶ added in v0.14.0
func ManagedHumanCapabilities() Capabilities
ManagedHumanCapabilities returns the capabilities of a managed principal: a human without an email whose profile and credentials are controlled by its managers, so it can use the UI but cannot manage its own profile or delegate (ADR-005).
func (Capabilities) ToMap ¶ added in v0.14.0
func (c Capabilities) ToMap() map[string]bool
ToMap returns the capabilities in the form stored on a principal.
type CreateAgentInput ¶
type CreateAgentInput struct {
Identifier string
DisplayName string
ModelID string
Version string
DelegatingPrincipalID *uuid.UUID
CapabilityConstraints []string
ResourceConstraints []string
MaxTokenLifetimeSeconds int
RequiresConfirmation bool
OrganizationID *uuid.UUID
AllowedScopes []string
Metadata map[string]any
}
CreateAgentInput contains fields for creating an agent principal.
type CreateApplicationInput ¶
type CreateApplicationInput struct {
ClientID string
DisplayName string
Description *string
LogoURL *string
AppType AppType
RedirectURIs []string
AllowedGrants []string
AllowedResponseTypes []string
AccessTokenTTLSeconds int
RefreshTokenTTLSeconds int
RefreshTokenRotation bool
FirstParty bool
Public bool
OrganizationID *uuid.UUID
AllowedScopes []string
Metadata map[string]any
}
CreateApplicationInput contains fields for creating an application principal.
type CreateHumanInput ¶
type CreateHumanInput struct {
Email string
DisplayName string
GivenName string
FamilyName string
AvatarURL *string
Locale string
Timezone string
OrganizationID *uuid.UUID
IsPlatformAdmin bool
AllowedScopes []string
Metadata map[string]any
}
CreateHumanInput contains fields for creating a human principal.
type CreateServiceInput ¶
type CreateServiceInput struct {
Identifier string
DisplayName string
ServiceType string
Description *string
CreatedBy *uuid.UUID
AllowedIPs []string
OrganizationID *uuid.UUID
AllowedScopes []string
Metadata map[string]any
}
CreateServiceInput contains fields for creating a service principal.
type DefaultService ¶
type DefaultService struct {
// contains filtered or unexported fields
}
DefaultService implements the Service interface.
func (*DefaultService) CreateAgent ¶
func (s *DefaultService) CreateAgent(ctx context.Context, input CreateAgentInput) (*Principal, error)
CreateAgent creates a new agent principal.
func (*DefaultService) CreateApplication ¶
func (s *DefaultService) CreateApplication(ctx context.Context, input CreateApplicationInput) (*Principal, error)
CreateApplication creates a new application principal.
func (*DefaultService) CreateHuman ¶
func (s *DefaultService) CreateHuman(ctx context.Context, input CreateHumanInput) (*Principal, error)
CreateHuman creates a new human principal.
func (*DefaultService) CreateHumanInTx ¶ added in v0.14.0
func (s *DefaultService) CreateHumanInTx(ctx context.Context, tx *ent.Tx, input CreateHumanInput) (*Principal, AfterCommit, error)
CreateHumanInTx implements HumanTxCreator.
func (*DefaultService) CreateService ¶
func (s *DefaultService) CreateService(ctx context.Context, input CreateServiceInput) (*Principal, error)
CreateService creates a new service principal.
func (*DefaultService) Deactivate ¶
Deactivate deactivates a principal. A deactivated principal holds no access: its memberships, application roles, resource grants, platform administration and manager relations stay in the tables, but their relationships are removed from the authorization graph before the deactivation commits. If the graph refuses, the principal stays active and the error is returned, so the call can be retried.
func (*DefaultService) GetByIdentifier ¶
func (s *DefaultService) GetByIdentifier(ctx context.Context, identifier string) (*Principal, error)
GetByIdentifier retrieves a principal by unique identifier.
func (*DefaultService) MarkEmailVerified ¶
MarkEmailVerified marks a human principal's email as verified.
func (*DefaultService) Reactivate ¶
Reactivate reactivates a principal and, after the change commits, writes back to the authorization graph the relationships its rows call for (failures returned in SyncModeStrict and logged otherwise; the graph reconciler repairs what is left).
func (*DefaultService) Update ¶
func (s *DefaultService) Update(ctx context.Context, id uuid.UUID, input UpdateInput) (*Principal, error)
Update updates an existing principal. A change of Active deactivates or reactivates it as Deactivate and Reactivate do, after the other fields are saved.
func (*DefaultService) UpdateAgent ¶
func (s *DefaultService) UpdateAgent(ctx context.Context, id uuid.UUID, input UpdateAgentInput) (*Principal, error)
UpdateAgent updates an agent principal.
func (*DefaultService) UpdateApplication ¶
func (s *DefaultService) UpdateApplication(ctx context.Context, id uuid.UUID, input UpdateApplicationInput) (*Principal, error)
UpdateApplication updates an application principal.
func (*DefaultService) UpdateHuman ¶
func (s *DefaultService) UpdateHuman(ctx context.Context, id uuid.UUID, input UpdateHumanInput) (*Principal, error)
UpdateHuman updates a human principal.
func (*DefaultService) UpdateLastLogin ¶
UpdateLastLogin updates the last login timestamp for a human principal.
func (*DefaultService) UpdateService ¶
func (s *DefaultService) UpdateService(ctx context.Context, id uuid.UUID, input UpdateServiceInput) (*Principal, error)
UpdateService updates a service principal.
type Human ¶
type Human struct {
Email string `json:"email,omitempty"` // absent for a managed principal
GivenName string `json:"given_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
Locale string `json:"locale,omitempty"`
Timezone string `json:"timezone,omitempty"`
IsPlatformAdmin bool `json:"is_platform_admin"`
LastLoginAt *time.Time `json:"last_login_at,omitempty"`
EmailVerifiedAt *time.Time `json:"email_verified_at,omitempty"`
}
Human represents human-specific principal data.
type HumanTxCreator ¶ added in v0.14.0
type HumanTxCreator interface {
// CreateHumanInTx writes the principal and its human row in tx and
// leaves committing to the caller. The returned AfterCommit registers
// the principal with the authorization syncer; call it after a
// successful commit. Nothing is synced if it is never called.
CreateHumanInTx(ctx context.Context, tx *ent.Tx, input CreateHumanInput) (*Principal, AfterCommit, error)
}
HumanTxCreator is implemented by services that can create a human principal inside a caller's transaction, so a larger operation such as signup is atomic.
type Principal ¶
type Principal struct {
ID uuid.UUID `json:"id"`
Type Type `json:"type"`
Identifier string `json:"identifier"` // Unique identifier (email, client_id, service@org)
DisplayName string `json:"display_name"`
OrganizationID *uuid.UUID `json:"organization_id,omitempty"`
Active bool `json:"active"`
Capabilities Capabilities `json:"capabilities"`
AllowedScopes []string `json:"allowed_scopes"`
Metadata map[string]any `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Type-specific extensions (only one will be populated based on Type)
Human *Human `json:"human,omitempty"`
Application *Application `json:"application,omitempty"`
Agent *Agent `json:"agent,omitempty"`
Service *ServiceData `json:"service,omitempty"`
}
Principal represents the core identity abstraction.
type Repository ¶
type Repository interface {
// GetByID retrieves a principal by ID.
GetByID(ctx context.Context, id uuid.UUID) (*Principal, error)
// GetByIdentifier retrieves a principal by unique identifier.
GetByIdentifier(ctx context.Context, identifier string) (*Principal, error)
// Create creates a new principal with its type-specific extension.
Create(ctx context.Context, p *Principal) error
// Update updates an existing principal.
Update(ctx context.Context, p *Principal) error
// Delete deletes a principal (soft delete via Active=false).
Delete(ctx context.Context, id uuid.UUID) error
// ListByOrganization lists principals in an organization.
ListByOrganization(ctx context.Context, orgID uuid.UUID, types []Type) ([]*Principal, error)
// ListByType lists principals of a specific type.
ListByType(ctx context.Context, t Type) ([]*Principal, error)
}
Repository defines the data access interface for principals.
type Service ¶
type Service interface {
// GetByID retrieves a principal by ID.
GetByID(ctx context.Context, id uuid.UUID) (*Principal, error)
// GetByIdentifier retrieves a principal by unique identifier.
GetByIdentifier(ctx context.Context, identifier string) (*Principal, error)
// CreateHuman creates a new human principal.
CreateHuman(ctx context.Context, input CreateHumanInput) (*Principal, error)
// CreateApplication creates a new application principal.
CreateApplication(ctx context.Context, input CreateApplicationInput) (*Principal, error)
// CreateAgent creates a new agent principal.
CreateAgent(ctx context.Context, input CreateAgentInput) (*Principal, error)
// CreateService creates a new service principal.
CreateService(ctx context.Context, input CreateServiceInput) (*Principal, error)
// Update updates an existing principal.
Update(ctx context.Context, id uuid.UUID, input UpdateInput) (*Principal, error)
// UpdateHuman updates a human principal.
UpdateHuman(ctx context.Context, id uuid.UUID, input UpdateHumanInput) (*Principal, error)
// UpdateApplication updates an application principal.
UpdateApplication(ctx context.Context, id uuid.UUID, input UpdateApplicationInput) (*Principal, error)
// UpdateAgent updates an agent principal.
UpdateAgent(ctx context.Context, id uuid.UUID, input UpdateAgentInput) (*Principal, error)
// UpdateService updates a service principal.
UpdateService(ctx context.Context, id uuid.UUID, input UpdateServiceInput) (*Principal, error)
// Deactivate deactivates a principal.
Deactivate(ctx context.Context, id uuid.UUID) error
// Reactivate reactivates a principal.
Reactivate(ctx context.Context, id uuid.UUID) error
}
Service defines the business logic interface for principals.
func NewService ¶
func NewService(client *ent.Client, opts ...ServiceOption) Service
NewService creates a new PrincipalService.
type ServiceData ¶
type ServiceData struct {
ServiceType string `json:"service_type"`
Description *string `json:"description,omitempty"`
CreatedBy *uuid.UUID `json:"created_by,omitempty"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
AllowedIPs []string `json:"allowed_ips,omitempty"`
}
ServiceData represents backend service-specific principal data.
type ServiceOption ¶
type ServiceOption func(*DefaultService)
ServiceOption configures a DefaultService.
func WithAccessChangeSink ¶ added in v0.14.0
func WithAccessChangeSink(sink accesschange.Sink) ServiceOption
WithAccessChangeSink announces deactivations to sink after they commit (ADR-010). The access-change record is written whether or not a sink is set.
func WithAuthzSyncer ¶
func WithAuthzSyncer(syncer authz.RelationshipSyncer) ServiceOption
WithAuthzSyncer sets the authorization syncer for keeping authz in sync with identity changes.
func WithLogger ¶
func WithLogger(logger *slog.Logger) ServiceOption
WithLogger sets the logger for the service.
func WithSyncMode ¶
func WithSyncMode(mode authz.SyncMode) ServiceOption
WithSyncMode sets the sync mode (strict or eventual).
type Type ¶
type Type string
Type represents the type of principal.
const ( // TypeHuman represents an interactive human user. TypeHuman Type = "human" // TypeApplication represents an OAuth 2.0 client application. TypeApplication Type = "application" // TypeAgent represents an AI assistant or automated agent. TypeAgent Type = "agent" // TypeService represents a backend service or system. TypeService Type = "service" )
type UpdateAgentInput ¶
type UpdateAgentInput struct {
UpdateInput
Version *string
CapabilityConstraints []string
ResourceConstraints []string
MaxTokenLifetimeSeconds *int
RequiresConfirmation *bool
}
UpdateAgentInput contains fields for updating an agent principal.
type UpdateApplicationInput ¶
type UpdateApplicationInput struct {
UpdateInput
Description *string
LogoURL *string
RedirectURIs []string
AllowedGrants []string
AllowedResponseTypes []string
AccessTokenTTLSeconds *int
RefreshTokenTTLSeconds *int
RefreshTokenRotation *bool
FirstParty *bool
}
UpdateApplicationInput contains fields for updating an application principal.
type UpdateHumanInput ¶
type UpdateHumanInput struct {
UpdateInput
GivenName *string
FamilyName *string
AvatarURL *string
Locale *string
Timezone *string
IsPlatformAdmin *bool
}
UpdateHumanInput contains fields for updating a human principal.
type UpdateInput ¶
type UpdateInput struct {
DisplayName *string
Active *bool
AllowedScopes []string
Capabilities *Capabilities
Metadata map[string]any
}
UpdateInput contains fields for updating any principal type.
type UpdateServiceInput ¶
type UpdateServiceInput struct {
UpdateInput
Description *string
AllowedIPs []string
}
UpdateServiceInput contains fields for updating a service principal.