Documentation
¶
Overview ¶
Package teams provides CRUD over operator-defined members and teams.
Members and teams are persisted as two opaque blobs ("members" and "teams") through storage.Provider, so whichever backend the rest of the service uses (file / redis / database) automatically applies. No extra config is required.
The store is purely a directory of identities — it does not (yet) participate in alert routing. Phase-2 work will read the per-member meta map (slack_id, telegram_id, ...) to choose channels per assignment.
Index ¶
- Constants
- Variables
- func DeriveAlias(name string) string
- type Member
- type MemberMeta
- type Store
- func (s *Store) CreateMember(in Member) (*Member, error)
- func (s *Store) CreateTeam(in Team) (*Team, error)
- func (s *Store) DeleteMember(id string) error
- func (s *Store) DeleteTeam(id string) error
- func (s *Store) GetMember(id string) (*Member, error)
- func (s *Store) GetTeam(id string) (*Team, error)
- func (s *Store) ListMembers() []*Member
- func (s *Store) ListTeams() []*Team
- func (s *Store) TeamExists(id string) bool
- func (s *Store) UpdateMember(id string, patch Member, replaceMeta bool) (*Member, error)
- func (s *Store) UpdateTeam(id string, patch Team, replaceMembers bool) (*Team, error)
- func (s *Store) ValidateMemberIDs(ids []string) error
- type Team
Constants ¶
const ( BlobMembers = "members" BlobTeams = "teams" )
Blob names used through storage.Provider.
Variables ¶
var ErrInvalid = errors.New("teams: invalid input")
ErrInvalid is returned for validation failures (empty name, etc).
var ErrNotFound = errors.New("teams: not found")
ErrNotFound is returned by Get/Update/Delete when the id is unknown.
Functions ¶
func DeriveAlias ¶
DeriveAlias produces a URL-safe lowercase slug from a human name. Mirrors the auto-fill the UI applies before the operator edits it. Exported for the controller's PATCH behavior and tests.
Types ¶
type Member ¶
type Member struct {
ID string `json:"id"`
Name string `json:"name"`
Alias string `json:"alias"`
Meta MemberMeta `json:"meta"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Member is an operator-defined person who can be assigned to incidents.
Alias is auto-derived from Name on first save when empty, but the UI allows operators to edit it independently afterwards.
Meta carries typed per-channel identifiers. Each field is optional; only set the ones the operator actually uses. Routing logic (Phase 2) reads these to pick channels per assignee — the store itself does not interpret them.
type MemberMeta ¶
type MemberMeta struct {
// Email address, also used for the SMTP/email channel.
Email string `json:"email,omitempty"`
// Slack member id (e.g. "U0123ABC"), NOT the @handle.
SlackID string `json:"slack_id,omitempty"`
// Telegram numeric user id as a string.
TelegramID string `json:"telegram_id,omitempty"`
// Microsoft Teams user principal name (UPN), typically the work email.
MSTeamsUPN string `json:"msteams_upn,omitempty"`
// Viber user id (channel API) for direct messaging.
ViberID string `json:"viber_id,omitempty"`
// Lark / Feishu open_id or union_id for direct messaging.
LarkID string `json:"lark_id,omitempty"`
// PagerDuty user id (used by future routing to attach assignees).
PagerDutyUserID string `json:"pagerduty_user_id,omitempty"`
// AWS Incident Manager contact ARN.
AWSIMContactARN string `json:"awsim_contact_arn,omitempty"`
// Phone number in E.164 (for future SMS / voice channels).
Phone string `json:"phone,omitempty"`
}
MemberMeta holds per-channel identifiers for a member. Fields are matched to the channels Versus already ships with; add a new field here (and to clone/equal helpers) when a new channel lands.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the in-process registry of members and teams. It loads state lazily from storage on first use and persists eagerly after every mutation. All exported methods are safe for concurrent use.
func NewStore ¶
NewStore returns a Store backed by the given storage provider. Provider must be non-nil.
func (*Store) CreateMember ¶
CreateMember inserts a new member. ID is server-generated. Alias is derived from Name when blank.
func (*Store) CreateTeam ¶
CreateTeam inserts a new team. MemberIDs are validated against the known member set; unknown ids are rejected as ErrInvalid.
func (*Store) DeleteMember ¶
DeleteMember removes a member. Returns ErrNotFound when unknown. Any team referencing the id keeps a dangling reference — callers are responsible for cleaning teams (the controller does this).
func (*Store) DeleteTeam ¶
DeleteTeam removes a team. Returns ErrNotFound when unknown.
func (*Store) ListMembers ¶
ListMembers returns members sorted by Name (case-insensitive).
func (*Store) TeamExists ¶
TeamExists reports whether a team id is known.
func (*Store) UpdateMember ¶
UpdateMember applies a partial patch. Empty strings on Name/Alias are treated as "no change". Pass replaceMeta=true to swap the entire MemberMeta struct (the zero value clears every channel id); replaceMeta=false leaves the existing meta untouched.
func (*Store) UpdateTeam ¶
UpdateTeam applies a partial patch. Pass replaceMembers=true to replace the member list (empty list clears it); false leaves the existing list alone.
func (*Store) ValidateMemberIDs ¶
ValidateMemberIDs is the public flavor of validateMemberIDsLocked, used by the incident-assignment controller.
type Team ¶
type Team struct {
ID string `json:"id"`
Name string `json:"name"`
Alias string `json:"alias"`
Description string `json:"description,omitempty"`
MemberIDs []string `json:"member_ids"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Team is an ordered group of member IDs.