relay

package
v0.44.19 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2026 License: MIT Imports: 39 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateOrLoadSecret

func GenerateOrLoadSecret(store *RelayStore, envSecret string) ([]byte, error)

GenerateOrLoadSecret returns the JWT signing secret. Priority: envSecret (from WT_JWT_SECRET) > relay_config DB > auto-generate.

func IssueWingJWT

func IssueWingJWT(secret []byte, userID, publicKey, wingID string) (string, time.Time, error)

IssueWingJWT creates a signed JWT for a wing connection.

func NewLoginProxy added in v0.23.0

func NewLoginProxy(loginAddr string) *httputil.ReverseProxy

NewLoginProxy creates a reverse proxy to the login node for edge nodes. Edge nodes proxy API, auth, and page requests to the login node while serving WebSocket connections directly.

func SeedDefaultSkills

func SeedDefaultSkills(store *RelayStore) error

Types

type BandwidthMeter

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

BandwidthMeter applies per-user rate limiting on relay traffic and periodically syncs usage to the DB.

func NewBandwidthMeter

func NewBandwidthMeter(bytesPerSec int, burst int, db *sql.DB) *BandwidthMeter

NewBandwidthMeter creates a meter with the given sustained rate (bytes/sec) and burst (bytes).

func (*BandwidthMeter) AddUsage added in v0.23.0

func (b *BandwidthMeter) AddUsage(userID string, bytes int64)

AddUsage adds external usage bytes (reported by edge nodes) to the local counters.

func (*BandwidthMeter) DrainCounters added in v0.23.0

func (b *BandwidthMeter) DrainCounters() map[string]int64

DrainCounters returns per-user byte counts accumulated since the last drain, then resets them. Used by edge nodes to report usage to login via the sync protocol.

func (*BandwidthMeter) ExceededMonthly added in v0.23.0

func (b *BandwidthMeter) ExceededMonthly(userID string) bool

ExceededMonthly returns true if a free-tier user has exceeded their monthly cap. Always returns false for pro/team users.

func (*BandwidthMeter) ExceededUsers added in v0.23.0

func (b *BandwidthMeter) ExceededUsers() []string

ExceededUsers returns user IDs that have exceeded their monthly bandwidth cap. Only meaningful on the login node where counters reflect cluster-wide totals.

func (*BandwidthMeter) InvalidateUser added in v0.23.0

func (b *BandwidthMeter) InvalidateUser(userID string)

func (*BandwidthMeter) IsExceeded added in v0.23.0

func (b *BandwidthMeter) IsExceeded(userID string) bool

IsExceeded returns true if a user has been flagged as over their monthly cap.

func (*BandwidthMeter) MonthlyUsage added in v0.23.0

func (b *BandwidthMeter) MonthlyUsage(userID string) int64

MonthlyUsage returns the user's current month bandwidth usage in bytes.

func (*BandwidthMeter) SeedFromDB added in v0.23.0

func (b *BandwidthMeter) SeedFromDB()

SeedFromDB loads current month's bandwidth totals from the DB into memory. Called on login startup to avoid resetting counters to zero.

func (*BandwidthMeter) SetExceeded added in v0.23.0

func (b *BandwidthMeter) SetExceeded(userIDs []string)

SetExceeded replaces the set of users who exceeded their monthly cap (pushed from login via sync).

func (*BandwidthMeter) SetTierLookup added in v0.23.0

func (b *BandwidthMeter) SetTierLookup(fn TierLookup)

SetTierLookup sets the function used to look up user tiers for rate differentiation.

func (*BandwidthMeter) StartSync

func (b *BandwidthMeter) StartSync(ctx context.Context, interval time.Duration)

StartSync syncs per-user bandwidth to the DB every interval. Only writes users with changes.

func (*BandwidthMeter) Wait

func (b *BandwidthMeter) Wait(ctx context.Context, userID string, n int) error

Wait blocks until the user's rate limiter allows n bytes, or ctx is done. Rejects immediately if the user has exceeded their monthly bandwidth cap.

type ConnectedWing

type ConnectedWing struct {
	ID           string
	UserID       string
	WingID       string
	PublicKey    string
	OrgID        string // org ID this wing serves
	Locked       bool
	AllowedCount int
	Conn         *websocket.Conn
	LastSeen     time.Time
}

ConnectedWing represents a wing connected via WebSocket.

type DeviceCodeRow

type DeviceCodeRow struct {
	Code      string
	UserCode  string
	UserID    *string
	DeviceID  string
	PublicKey *string
	CreatedAt time.Time
	ExpiresAt time.Time
	Claimed   bool
}

type Entitlement added in v0.23.0

type Entitlement struct {
	ID             string
	UserID         string
	SubscriptionID string
	CreatedAt      time.Time
}

type EntitlementCache added in v0.23.0

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

EntitlementCache caches user tier info on edge nodes, polling the login node periodically.

func NewEntitlementCache added in v0.23.0

func NewEntitlementCache(loginAddr string) *EntitlementCache

func (*EntitlementCache) GetTier added in v0.23.0

func (c *EntitlementCache) GetTier(userID string) string

GetTier returns the cached tier for a user, defaulting to "free".

func (*EntitlementCache) StartSync added in v0.23.0

func (c *EntitlementCache) StartSync(ctx context.Context, interval time.Duration)

StartSync begins periodic polling of the login node for entitlement data.

type EntitlementEntry added in v0.23.0

type EntitlementEntry struct {
	UserID string `json:"user_id"`
	Tier   string `json:"tier"`
}

EntitlementEntry is a user's entitlement info for edge node caching.

type Org added in v0.23.0

type Org struct {
	ID          string
	Name        string
	Slug        string
	OwnerUserID string
	MaxSeats    int
	CreatedAt   time.Time
}

Org represents an organization that can share wings among members.

type OrgInvite added in v0.23.0

type OrgInvite struct {
	ID        string
	OrgID     string
	Email     string
	Token     string
	InvitedBy string
	Role      string
	CreatedAt time.Time
	ClaimedAt *time.Time
}

OrgInvite represents a pending invite to an org.

type OrgMember added in v0.23.0

type OrgMember struct {
	OrgID     string
	UserID    string
	Role      string // "owner", "admin", "member"
	CreatedAt time.Time
}

OrgMember represents a user's membership in an org.

type PTYRoute added in v0.44.4

type PTYRoute struct {
	BrowserConn *websocket.Conn
	UserID      string // bandwidth metering only
	// contains filtered or unexported fields
}

PTYRoute is a minimal routing entry for wing→browser output forwarding. No session metadata — the wing owns all session intelligence.

type PTYRoutes added in v0.44.4

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

PTYRoutes tracks active PTY routing entries.

func NewPTYRoutes added in v0.44.4

func NewPTYRoutes() *PTYRoutes

func (*PTYRoutes) ClearBrowser added in v0.44.4

func (r *PTYRoutes) ClearBrowser(conn *websocket.Conn)

ClearBrowser nils the BrowserConn on all routes owned by this connection.

func (*PTYRoutes) Get added in v0.44.4

func (r *PTYRoutes) Get(sessionID string) *PTYRoute

func (*PTYRoutes) Remove added in v0.44.4

func (r *PTYRoutes) Remove(sessionID string)

func (*PTYRoutes) Set added in v0.44.4

func (r *PTYRoutes) Set(sessionID string, route *PTYRoute)

type PasskeyCredential added in v0.34.0

type PasskeyCredential struct {
	ID           string
	UserID       string
	CredentialID []byte
	PublicKey    []byte // raw P-256: 64 bytes (X||Y)
	SignCount    int
	Label        string
	CreatedAt    time.Time
}

PasskeyCredential represents a stored WebAuthn credential.

type RateLimiter added in v0.12.0

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

RateLimiter applies per-IP request rate limiting. "Friends and family" limits — just enough to prevent abuse.

func NewRateLimiter added in v0.12.0

func NewRateLimiter(reqPerSec float64, burst int) *RateLimiter

NewRateLimiter creates a per-IP rate limiter. reqPerSec is the sustained rate, burst is the max burst size.

func (*RateLimiter) Allow added in v0.12.0

func (rl *RateLimiter) Allow(ip string) bool

Allow returns true if the request is within rate limits for the given IP.

func (*RateLimiter) Middleware added in v0.12.0

func (rl *RateLimiter) Middleware(next http.Handler) http.Handler

Middleware wraps an http.Handler with rate limiting.

type RelayStore

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

func OpenRelay

func OpenRelay(dsn string) (*RelayStore, error)

func (*RelayStore) AddOrgMember added in v0.23.0

func (s *RelayStore) AddOrgMember(orgID, userID, role string) error

AddOrgMember adds a user to an org, enforcing max_seats.

func (*RelayStore) AppendAudit

func (s *RelayStore) AppendAudit(userID, event string, detail *string) error

func (*RelayStore) BackfillProUsers added in v0.23.0

func (s *RelayStore) BackfillProUsers() error

func (*RelayStore) ClaimDeviceCode

func (s *RelayStore) ClaimDeviceCode(code, userID string) error

func (*RelayStore) Close

func (s *RelayStore) Close() error
func (s *RelayStore) ConsumeMagicLink(token string) (string, error)

func (*RelayStore) ConsumeOrgInvite added in v0.23.0

func (s *RelayStore) ConsumeOrgInvite(token string) (string, string, string, error)

ConsumeOrgInvite validates a token, marks it claimed, returns email, orgID, and role.

func (*RelayStore) CountEntitlementsBySub added in v0.23.0

func (s *RelayStore) CountEntitlementsBySub(subID string) (int, error)

func (*RelayStore) CountOrgMembers added in v0.23.0

func (s *RelayStore) CountOrgMembers(orgID string) (int, error)

CountOrgMembers returns the number of members in an org.

func (*RelayStore) CountOrgsOwnedByUser added in v0.32.1

func (s *RelayStore) CountOrgsOwnedByUser(userID string) (int, error)

CountOrgsOwnedByUser returns the number of orgs a user has created.

func (*RelayStore) CreateDeviceCode

func (s *RelayStore) CreateDeviceCode(code, userCode, deviceID string, expiresAt time.Time) error

func (*RelayStore) CreateDeviceCodeWithKey

func (s *RelayStore) CreateDeviceCodeWithKey(code, userCode, deviceID, publicKey string, expiresAt time.Time) error

func (*RelayStore) CreateDeviceToken

func (s *RelayStore) CreateDeviceToken(token, userID, deviceID string, expiresAt *time.Time) error

func (*RelayStore) CreateEntitlement added in v0.23.0

func (s *RelayStore) CreateEntitlement(ent *Entitlement) error

func (*RelayStore) CreateLocalUser added in v0.7.4

func (s *RelayStore) CreateLocalUser() (*User, string, error)

CreateLocalUser creates the local-mode user and a non-expiring device token. Returns the social user, device token string, and whether the user already existed.

func (s *RelayStore) CreateMagicLink(id, email, token string, expiresAt time.Time) error

func (*RelayStore) CreateOrg added in v0.23.0

func (s *RelayStore) CreateOrg(id, name, slug, ownerUserID string) error

CreateOrg creates a new org and adds the owner as an owner member.

func (*RelayStore) CreateOrgInvite added in v0.23.0

func (s *RelayStore) CreateOrgInvite(id, orgID, email, token, invitedBy, role string) error

CreateOrgInvite creates a pending invite.

func (*RelayStore) CreatePasskeyCredential added in v0.34.0

func (s *RelayStore) CreatePasskeyCredential(id, userID string, credentialID, publicKey []byte, label string) error

CreatePasskeyCredential stores a new passkey credential.

func (*RelayStore) CreateSession

func (s *RelayStore) CreateSession(token, userID string, expiresAt time.Time) error

func (*RelayStore) CreateSkill

func (s *RelayStore) CreateSkill(name, description, category, agent, tags, content, sha256, publisher, sourceURL string, weight int) error

func (*RelayStore) CreateSubscription added in v0.23.0

func (s *RelayStore) CreateSubscription(sub *Subscription) error

func (*RelayStore) CreateUser

func (s *RelayStore) CreateUser(id string) error

func (*RelayStore) CreateUserDev added in v0.23.0

func (s *RelayStore) CreateUserDev() (*User, error)

CreateUserDev creates a dev-mode social user if one doesn't exist.

func (*RelayStore) DB

func (s *RelayStore) DB() *sql.DB

DB returns the underlying database connection.

func (*RelayStore) DeleteEntitlementByUserAndSub added in v0.23.0

func (s *RelayStore) DeleteEntitlementByUserAndSub(userID, subID string) error

func (*RelayStore) DeleteEntitlementsBySub added in v0.23.0

func (s *RelayStore) DeleteEntitlementsBySub(subID string) ([]string, error)

func (*RelayStore) DeleteLabel added in v0.23.0

func (s *RelayStore) DeleteLabel(targetID, scopeType, scopeID string) error

DeleteLabel removes a label for a target at a given scope.

func (*RelayStore) DeleteOrg added in v0.32.5

func (s *RelayStore) DeleteOrg(orgID string) error

DeleteOrg removes an org and all its members and invites.

func (*RelayStore) DeletePasskeyCredential added in v0.34.0

func (s *RelayStore) DeletePasskeyCredential(id, userID string) error

DeletePasskeyCredential removes a passkey credential by ID, scoped to user.

func (*RelayStore) DeleteSession

func (s *RelayStore) DeleteSession(token string) error

func (*RelayStore) DeleteSkill

func (s *RelayStore) DeleteSkill(name string) error

func (*RelayStore) DeleteToken

func (s *RelayStore) DeleteToken(token string) error

func (*RelayStore) GetActiveOrgSubscription added in v0.23.0

func (s *RelayStore) GetActiveOrgSubscription(orgID string) (*Subscription, error)

func (*RelayStore) GetActivePersonalSubscription added in v0.23.0

func (s *RelayStore) GetActivePersonalSubscription(userID string) (*Subscription, error)

func (*RelayStore) GetDeviceCode

func (s *RelayStore) GetDeviceCode(code string) (*DeviceCodeRow, error)

func (*RelayStore) GetDeviceCodeByUserCode

func (s *RelayStore) GetDeviceCodeByUserCode(userCode string) (*DeviceCodeRow, error)

GetDeviceCodeByUserCode finds a device code by user_code.

func (*RelayStore) GetInviteByToken added in v0.32.4

func (s *RelayStore) GetInviteByToken(token string) (*OrgInvite, error)

GetInviteByToken returns an invite by its token (claimed or not).

func (*RelayStore) GetOrCreateUserByEmail added in v0.23.0

func (s *RelayStore) GetOrCreateUserByEmail(email string) (*User, error)

func (*RelayStore) GetOrgByID added in v0.23.0

func (s *RelayStore) GetOrgByID(id string) (*Org, error)

GetOrgByID returns an org by ID.

func (*RelayStore) GetOrgBySlug added in v0.23.0

func (s *RelayStore) GetOrgBySlug(slug string) (*Org, error)

GetOrgBySlug returns an org by slug.

func (*RelayStore) GetOrgMemberRole added in v0.23.0

func (s *RelayStore) GetOrgMemberRole(orgID, userID string) string

GetOrgMemberRole returns the role of a user in an org, or "" if not a member.

func (*RelayStore) GetRelayConfig

func (s *RelayStore) GetRelayConfig(key string) (string, error)

GetRelayConfig reads a value from the relay_config table.

func (*RelayStore) GetSession

func (s *RelayStore) GetSession(token string) (*User, error)

func (*RelayStore) GetSkill

func (s *RelayStore) GetSkill(name string) (*SkillRow, error)

func (*RelayStore) GetUserByEmail added in v0.23.0

func (s *RelayStore) GetUserByEmail(email string) (*User, error)

GetUserByEmail returns a user by email.

func (*RelayStore) GetUserByID added in v0.23.0

func (s *RelayStore) GetUserByID(id string) (*User, error)

GetUserByID returns a user by their ID.

func (*RelayStore) GetUserByProvider added in v0.23.0

func (s *RelayStore) GetUserByProvider(provider, providerID string) (*User, error)

func (*RelayStore) HasPersonalSubscription added in v0.38.0

func (s *RelayStore) HasPersonalSubscription(userID string) bool

HasPersonalSubscription returns true if the user has an active personal (non-org) subscription.

func (*RelayStore) IsOrgMember added in v0.23.0

func (s *RelayStore) IsOrgMember(orgID, userID string) bool

IsOrgMember returns true if the user is a member of the org.

func (*RelayStore) IsUserPro added in v0.23.0

func (s *RelayStore) IsUserPro(userID string) bool

func (*RelayStore) ListOrgMembers added in v0.23.0

func (s *RelayStore) ListOrgMembers(orgID string) ([]*OrgMember, error)

ListOrgMembers returns all members of an org with their user info.

func (*RelayStore) ListOrgsForUser added in v0.23.0

func (s *RelayStore) ListOrgsForUser(userID string) ([]*Org, error)

ListOrgsForUser returns all orgs a user belongs to.

func (*RelayStore) ListPasskeyCredentials added in v0.34.0

func (s *RelayStore) ListPasskeyCredentials(userID string) ([]*PasskeyCredential, error)

ListPasskeyCredentials returns all passkey credentials for a user.

func (*RelayStore) ListPendingInvites added in v0.23.0

func (s *RelayStore) ListPendingInvites(orgID string) ([]*OrgInvite, error)

ListPendingInvites returns unclaimed invites for an org.

func (*RelayStore) ListSkills

func (s *RelayStore) ListSkills(category string) ([]*SkillRow, error)

func (*RelayStore) RemoveOrgMember added in v0.23.0

func (s *RelayStore) RemoveOrgMember(orgID, userID string) error

RemoveOrgMember removes a user from an org.

func (*RelayStore) ResolveLabel added in v0.23.0

func (s *RelayStore) ResolveLabel(targetID, userID, orgID string) string

ResolveLabel returns the best label for a target: org-scoped first, then personal.

func (*RelayStore) ResolveLabels added in v0.23.0

func (s *RelayStore) ResolveLabels(targetIDs []string, userID, orgID string) map[string]string

ResolveLabels batch-resolves labels for multiple targets.

func (*RelayStore) ResolveOrg added in v0.33.0

func (s *RelayStore) ResolveOrg(ref, userID string) (*Org, error)

ResolveOrg resolves an org reference (ID or slug) for a specific user. It tries ID first, then slug. If multiple orgs match the slug, it returns an error listing the ambiguous matches.

func (*RelayStore) RevokeOrgInvite added in v0.32.4

func (s *RelayStore) RevokeOrgInvite(token string) error

RevokeOrgInvite deletes a pending invite by token.

func (*RelayStore) SearchSkills

func (s *RelayStore) SearchSkills(query string) ([]*SkillRow, error)

func (*RelayStore) SetLabel added in v0.23.0

func (s *RelayStore) SetLabel(targetID, scopeType, scopeID, label string) error

SetLabel upserts a label for a target (wing or session).

func (*RelayStore) SetOrgMaxSeats added in v0.23.0

func (s *RelayStore) SetOrgMaxSeats(orgID string, seats int) error

SetOrgMaxSeats updates the max seat count for an org.

func (*RelayStore) SetRelayConfig

func (s *RelayStore) SetRelayConfig(key, value string) error

SetRelayConfig writes a value to the relay_config table.

func (*RelayStore) UpdatePasskeySignCount added in v0.34.0

func (s *RelayStore) UpdatePasskeySignCount(id string, count int) error

UpdatePasskeySignCount increments the sign count for a credential.

func (*RelayStore) UpdateSubscriptionSeats added in v0.23.0

func (s *RelayStore) UpdateSubscriptionSeats(subID string, seats int) error

UpdateSubscriptionSeats updates the seat count on a subscription.

func (*RelayStore) UpdateSubscriptionStatus added in v0.23.0

func (s *RelayStore) UpdateSubscriptionStatus(subID, status string) error

func (*RelayStore) UpdateUserEmail added in v0.23.0

func (s *RelayStore) UpdateUserEmail(userID, email string) error

UpdateUserEmail sets the email for a user.

func (*RelayStore) UpdateUserTier added in v0.23.0

func (s *RelayStore) UpdateUserTier(userID, tier string) error

UpdateUserTier sets the tier for a user.

func (*RelayStore) UpsertUser added in v0.23.0

func (s *RelayStore) UpsertUser(u *User) error

func (*RelayStore) ValidateToken

func (s *RelayStore) ValidateToken(token string) (userID string, deviceID string, err error)

type Server

type Server struct {
	Store          *RelayStore
	Config         ServerConfig
	DevTemplateDir string // if set, re-read templates from disk on each request
	DevMode        bool   // if set, auto-claim device codes with test-user
	LocalMode      bool   // if set, bypass auth — single-user, zero-config

	Wings     *WingRegistry
	PTY       *PTYRoutes
	Bandwidth *BandwidthMeter
	RateLimit *RateLimiter

	// Cluster routing (multi-node)
	WingMap *WingMap

	EntitlementCache *EntitlementCache
	// contains filtered or unexported fields
}

func NewServer

func NewServer(store *RelayStore, cfg ServerConfig) *Server

func (*Server) GracefulShutdown added in v0.23.0

func (s *Server) GracefulShutdown(httpSrv *http.Server, timeout time.Duration) error

GracefulShutdown sends relay.restart to all connected WebSockets, then shuts down the HTTP server.

func (*Server) IsEdge added in v0.23.0

func (s *Server) IsEdge() bool

IsEdge returns true if this node is an edge relay (no SQLite).

func (*Server) IsLogin added in v0.23.0

func (s *Server) IsLogin() bool

IsLogin returns true if this node is the login/DB node.

func (*Server) MachineID added in v0.23.0

func (s *Server) MachineID() string

MachineID returns this node's unique machine identifier.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*Server) SetLocalUser added in v0.7.4

func (s *Server) SetLocalUser(u *User)

func (*Server) SetLoginProxy added in v0.23.0

func (s *Server) SetLoginProxy(p http.Handler)

SetLoginProxy sets the reverse proxy used by edge nodes to forward requests to the login node.

func (*Server) SetSessionCache added in v0.23.0

func (s *Server) SetSessionCache(sc *SessionCache)

SetSessionCache sets the session cache for edge nodes.

func (*Server) StartEdgeSync added in v0.23.0

func (s *Server) StartEdgeSync(ctx context.Context, loginAddr string, interval time.Duration)

StartEdgeSync runs the edge-to-login reconcile loop.

type ServerConfig

type ServerConfig struct {
	BaseURL            string
	AppHost            string // e.g. "app.wingthing.ai" — serve SPA at root
	WSHost             string // e.g. "ws.wingthing.ai" — WebSocket only
	JWTSecret          string // base64-encoded; overrides DB-stored secret
	GitHubClientID     string
	GitHubClientSecret string
	GoogleClientID     string
	GoogleClientSecret string
	SMTPHost           string
	SMTPPort           string
	SMTPUser           string
	SMTPPass           string
	SMTPFrom           string
	NodeRole           string // "login", "edge", or "" (single node)
	LoginNodeAddr      string // internal address of login node (for edge nodes)
	FlyMachineID       string // from FLY_MACHINE_ID env var
	FlyRegion          string // from FLY_REGION env var
	FlyAppName         string // from FLY_APP_NAME env var
}

type SessionCache added in v0.23.0

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

SessionCache caches session token → user info on edge nodes. Each validated session is cached for 5 minutes to avoid hitting the login node on every request.

func NewSessionCache added in v0.23.0

func NewSessionCache() *SessionCache

func (*SessionCache) Validate added in v0.23.0

func (sc *SessionCache) Validate(token, loginAddr string) *User

Validate checks the cache or calls the login node to validate a session token.

type SessionValidation added in v0.23.0

type SessionValidation struct {
	UserID      string   `json:"user_id"`
	DisplayName string   `json:"display_name"`
	Tier        string   `json:"tier"`
	OrgIDs      []string `json:"org_ids"`
}

SessionValidation is the response from the session validation endpoint.

type SkillRow

type SkillRow struct {
	Name        string
	Description string
	Category    string
	Agent       string
	Tags        string
	Content     string
	SHA256      string
	Publisher   string
	SourceURL   string
	Weight      int
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

type Subscription added in v0.23.0

type Subscription struct {
	ID                   string
	UserID               *string
	OrgID                *string
	Plan                 string
	Status               string
	Seats                int
	StripeSubscriptionID *string
	CreatedAt            time.Time
	UpdatedAt            time.Time
}

type TierLookup added in v0.23.0

type TierLookup func(userID string) string

TierLookup returns a user's tier string ("free", "pro", "team").

type User added in v0.23.0

type User struct {
	ID          string
	Provider    string
	ProviderID  string
	DisplayName string
	AvatarURL   *string
	Email       *string
	Tier        string // "free", "pro", "team"
	IsPro       bool
	CreatedAt   time.Time
	OrgIDs      []string // transient: populated by session cache on edge nodes
}

User represents an authenticated user (via OAuth, magic link, or local mode).

type WingClaims

type WingClaims struct {
	jwt.RegisteredClaims
	PublicKey string `json:"pub,omitempty"`
	WingID    string `json:"wing,omitempty"`
}

WingClaims are the JWT claims for a wing connection.

func ValidateWingJWT

func ValidateWingJWT(secret []byte, tokenString string) (*WingClaims, error)

ValidateWingJWT verifies a JWT and returns the claims.

type WingEvent added in v0.7.5

type WingEvent struct {
	Type         string `json:"type"` // "wing.online", "wing.offline", "session.attention"
	WingID       string `json:"wing_id"`
	PublicKey    string `json:"public_key,omitempty"`
	SessionID    string `json:"session_id,omitempty"`
	Locked       *bool  `json:"locked,omitempty"`
	AllowedCount *int   `json:"allowed_count,omitempty"`
}

WingEvent is sent to dashboard subscribers for wing/session lifecycle events.

type WingLocation added in v0.44.9

type WingLocation struct {
	MachineID    string
	UserID       string
	OrgID        string
	PublicKey    string
	Locked       bool
	AllowedCount int
	RegisteredAt time.Time
}

WingLocation tracks where a wing is connected across the cluster.

type WingMap added in v0.44.9

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

WingMap is the global registry of all wings, stored on the login node.

func NewWingMap added in v0.44.9

func NewWingMap() *WingMap

func (*WingMap) All added in v0.44.9

func (m *WingMap) All() map[string]WingLocation

All returns a snapshot of all wings.

func (*WingMap) Deregister added in v0.44.9

func (m *WingMap) Deregister(wingID string)

func (*WingMap) EdgeIDs added in v0.44.9

func (m *WingMap) EdgeIDs() []string

EdgeIDs returns all known edge machine IDs, expiring dead edges (30s timeout).

func (*WingMap) Locate added in v0.44.9

func (m *WingMap) Locate(wingID string) (WingLocation, bool)

func (*WingMap) ReconcileFull added in v0.44.13

func (m *WingMap) ReconcileFull(machineID string, activeWings map[string]bool, snapshotAt time.Time)

ReconcileFull replaces wing state for a machine using the edge's authoritative snapshot. Wings registered AFTER snapshotAt are preserved (arrived via real-time event after snapshot).

func (*WingMap) Register added in v0.44.9

func (m *WingMap) Register(wingID string, loc WingLocation)

type WingRegistry

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

WingRegistry tracks all connected wings.

func NewWingRegistry

func NewWingRegistry() *WingRegistry

func (*WingRegistry) Add

func (r *WingRegistry) Add(w *ConnectedWing)

func (*WingRegistry) All added in v0.23.0

func (r *WingRegistry) All() []*ConnectedWing

All returns all connected wings.

func (*WingRegistry) BroadcastAll added in v0.23.0

func (r *WingRegistry) BroadcastAll(ctx context.Context, data []byte)

BroadcastAll sends a message to every connected wing.

func (*WingRegistry) CloseAll added in v0.23.0

func (r *WingRegistry) CloseAll()

CloseAll closes all connected wing WebSockets.

func (*WingRegistry) CountForUser

func (r *WingRegistry) CountForUser(userID string) int

CountForUser returns the number of wings connected for a given user.

func (*WingRegistry) FindByID

func (r *WingRegistry) FindByID(wingID string) *ConnectedWing

func (*WingRegistry) ListForUser

func (r *WingRegistry) ListForUser(userID string) []*ConnectedWing

ListForUser returns all wings connected for a given user.

func (*WingRegistry) Remove

func (r *WingRegistry) Remove(id string) *ConnectedWing

func (*WingRegistry) Subscribe added in v0.7.5

func (r *WingRegistry) Subscribe(userID string, orgIDs []string, ch chan WingEvent)

Subscribe registers a dashboard subscriber with its org memberships. Events are delivered if the subscriber's userID matches the wing owner OR if the wing's orgID appears in the subscriber's orgIDs.

func (*WingRegistry) Touch

func (r *WingRegistry) Touch(wingID string)

func (*WingRegistry) Unsubscribe added in v0.7.5

func (r *WingRegistry) Unsubscribe(userID string, ch chan WingEvent)

func (*WingRegistry) UpdateConfig added in v0.37.0

func (r *WingRegistry) UpdateConfig(id string, locked bool, allowedCount int) *ConnectedWing

UpdateConfig updates a wing's lock state. Returns the wing for event dispatch.

func (*WingRegistry) UpdateUserOrgs added in v0.44.6

func (r *WingRegistry) UpdateUserOrgs(userID string, orgIDs []string) bool

UpdateUserOrgs updates the org list for all active subscribers of a user. Returns true if the user had any active subscribers (i.e., was worth updating).

Jump to

Keyboard shortcuts

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