team

package
v0.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package team is the library-first service layer for the multi-user ("team/family") system of record: users, roles, the allowlist, and — in later phases — chats and authentication.

Authorization is enforced twice by design: the service checks the acting user before issuing queries (clear errors), and row-level security in PostgreSQL backstops every query regardless (defense in depth). Never infer authorization from ent errors alone: an RLS-filtered UPDATE can surface as a not-found rather than a denial.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrForbidden is returned when the actor lacks permission.
	ErrForbidden = errors.New("forbidden")

	// ErrInvalidUsername is returned for usernames outside the allowed form.
	ErrInvalidUsername = errors.New("invalid username: use 3-32 characters of a-z, 0-9, '-' or '_', starting with a letter or digit")

	// ErrInvalidEmail is returned for unparseable email addresses.
	ErrInvalidEmail = errors.New("invalid email address")

	// ErrNotFound is returned when the referenced entity does not exist
	// (or is invisible to the actor — indistinguishable by design).
	ErrNotFound = errors.New("not found")
)

Sentinel errors returned by the service layer.

Functions

This section is empty.

Types

type Actor

type Actor struct {
	UserID     uuid.UUID
	Superadmin bool
}

Actor identifies the authenticated caller of a service operation.

type Config

type Config struct {
	// SuperadminEmail bootstraps the superadmin: the first login by this
	// email creates (or, if no superadmin exists yet, promotes) the
	// superadmin user. Later config changes never demote an existing one.
	SuperadminEmail string

	// AgentHandle is the @-mention handle of the agent (default "omniagent").
	AgentHandle string

	// Logger defaults to slog.Default().
	Logger *slog.Logger
}

Config configures the team service.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service exposes team operations over the RLS-scoped store.

func NewService

func NewService(st *store.Store, cfg Config) (*Service, error)

NewService creates the team service.

func (*Service) AgentHandle

func (s *Service) AgentHandle() string

AgentHandle returns the agent's @-mention handle.

func (*Service) AllowlistAdd

func (s *Service) AllowlistAdd(ctx context.Context, actor Actor, email, note string) (*ent.AllowlistEntry, error)

AllowlistAdd approves an email for login. Superadmin only.

func (*Service) AllowlistList

func (s *Service) AllowlistList(ctx context.Context, actor Actor) ([]*ent.AllowlistEntry, error)

AllowlistList returns all allowlisted emails. Superadmin only.

func (*Service) AllowlistRemove

func (s *Service) AllowlistRemove(ctx context.Context, actor Actor, email string) error

AllowlistRemove revokes an email's approval. Superadmin only. Removing an email does not delete an existing user; disable the user for that.

func (*Service) EnsureUser

func (s *Service) EnsureUser(ctx context.Context, email string) (u *ent.User, created bool, err error)

EnsureUser returns the user for a verified email, creating it on first login. Superadmin bootstrap happens here:

  • A newly created user whose email matches the configured superadmin email gets the superadmin role.
  • An existing member with that email is promoted only when no superadmin exists yet (config set after their first login).
  • Changing the configured email later never demotes an existing superadmin — demotion is an explicit administrative act, not a config side effect.

The caller (auth layer) must have verified both the email and its allowlist status; EnsureUser does not re-check the allowlist.

func (*Service) GetSelf

func (s *Service) GetSelf(ctx context.Context, actor Actor) (*ent.User, error)

GetSelf returns the actor's own user record.

func (*Service) IsEmailAllowed

func (s *Service) IsEmailAllowed(ctx context.Context, email string) (bool, error)

IsEmailAllowed reports whether an email may log in: it is allowlisted or is the configured superadmin email. Runs in the system context — it is consulted by the auth layer before any user exists.

func (*Service) ListIdentities added in v0.17.0

func (s *Service) ListIdentities(ctx context.Context, actor Actor, userIDs []uuid.UUID) (map[uuid.UUID][]string, error)

ListIdentities returns each given user's linked sign-in provider names ("magic_link", "google", "github"), keyed by user ID. Superadmin only; used by the admin members view (RMI-OMNIAGENT-122).

func (*Service) ListUsers

func (s *Service) ListUsers(ctx context.Context, actor Actor) ([]*ent.User, error)

ListUsers returns all users. Superadmin only.

func (*Service) RenameUser

func (s *Service) RenameUser(ctx context.Context, actor Actor, userID uuid.UUID, username string) error

RenameUser changes a user's username. Members may rename themselves; the superadmin may rename anyone (US-3 covers renaming themselves).

func (*Service) SetDisplayName

func (s *Service) SetDisplayName(ctx context.Context, actor Actor, userID uuid.UUID, name string) error

SetDisplayName changes a user's display name (self, or superadmin).

func (*Service) SetUserStatus

func (s *Service) SetUserStatus(ctx context.Context, actor Actor, userID uuid.UUID, status entuser.Status) error

SetUserStatus enables or disables a user. Superadmin only; the superadmin cannot disable themselves (lockout guard).

Directories

Path Synopsis
Package agentruntime provides per-agent runtime instances for team mode (RMI-OMNIAGENT-309).
Package agentruntime provides per-agent runtime instances for team mode (RMI-OMNIAGENT-309).
Package agents is the virtual-agents service layer (INIT-OMNIAGENT-005): a persisted agent = a persona/model bound to an enabled subset of the deployment's skills, its per-agent owner/maintainer roles, an authorization matrix (Can), and a private/listed + featured registry.
Package agents is the virtual-agents service layer (INIT-OMNIAGENT-005): a persisted agent = a persona/model bound to an enabled subset of the deployment's skills, its per-agent owner/maintainer roles, an authorization matrix (Can), and a private/listed + featured registry.
Package auth implements passwordless, allowlist-closed authentication for team mode: magic-link issuance/verification and server-side cookie sessions.
Package auth implements passwordless, allowlist-closed authentication for team mode: magic-link issuance/verification and server-side cookie sessions.
Package chats is the chat/membership/message service layer: private (DM) and group chats, membership, message persistence, and the agent turn.
Package chats is the chat/membership/message service layer: private (DM) and group chats, membership, message persistence, and the agent turn.
ent
Package ent holds the generated Ent client for the team system of record.
Package ent holds the generated Ent client for the team system of record.
schema
Package schema defines the Ent schemas for the team (multi-user) system of record.
Package schema defines the Ent schemas for the team (multi-user) system of record.
Package mail delivers team emails (magic-link logins).
Package mail delivers team emails (magic-link logins).
Package secrets provides the team-mode secret store: an OmniVault-backed, multi-tenant vault whose per-agent namespaces let a runtime instance (RMI-OMNIAGENT-310) load only its own agent's secrets.
Package secrets provides the team-mode secret store: an OmniVault-backed, multi-tenant vault whose per-agent namespaces let a runtime instance (RMI-OMNIAGENT-310) load only its own agent's secrets.
Package store opens the team database and scopes every query to the authenticated user.
Package store opens the team database and scopes every query to the authenticated user.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL