model

package
v0.40.0 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AuditActorSystem = "System"

	AuditActorTypeUser   = "User"
	AuditActorTypeSystem = "System"
	AuditActorTypeMCP    = "MCP"
)

Define actor types

View Source
const (
	AuditEventSystemStart = "System Start"

	// Auth
	AuditEventAuthFailed  = "Login Failed"
	AuditEventAuthOk      = "Login Success"
	AuditEventAuthBlocked = "Login Blocked"

	// Anomaly detection (Knot Pro) — emitted when a detection rule fires over
	// the audit event stream
	AuditEventAnomalyDetected = "Anomaly Detected"

	// Groups
	AuditEventGroupCreate = "Group Create"
	AuditEventGroupUpdate = "Group Update"
	AuditEventGroupDelete = "Group Delete"

	// Roles
	AuditEventRoleCreate = "Role Create"
	AuditEventRoleUpdate = "Role Update"
	AuditEventRoleDelete = "Role Delete"

	// Tunnels
	AuditEventTunnelCreate = "Tunnel Create"
	AuditEventTunnelDelete = "Tunnel Close"

	// Spaces
	AuditEventSpaceCreate    = "Space Create"
	AuditEventSpaceUpdate    = "Space Update"
	AuditEventSpaceDelete    = "Space Delete"
	AuditEventSpaceStart     = "Space Start"
	AuditEventSpaceStop      = "Space Stop"
	AuditEventSpaceRestart   = "Space Restart"
	AuditEventSpaceTransfer  = "Space Transfer"
	AuditEventSpaceShare     = "Space Shared"
	AuditEventSpaceStopShare = "Space Stop Share"
	AuditEventSpaceRestrict  = "Space Restrict"

	// Templates
	AuditEventTemplateCreate = "Template Create"
	AuditEventTemplateUpdate = "Template Update"
	AuditEventTemplateDelete = "Template Delete"

	// Variables
	AuditEventVarCreate = "Variable Create"
	AuditEventVarUpdate = "Variable Update"
	AuditEventVarDelete = "Variable Delete"

	// Users
	AuditEventUserCreate       = "User Create"
	AuditEventUserUpdate       = "User Update"
	AuditEventUserDelete       = "User Delete"
	AuditEventUserLink         = "User Link"
	AuditEventUserUnlink       = "User Unlink"
	AuditEventUserSwitch       = "User Switch"
	AuditEventUserSwitchDenied = "User Switch Denied"

	// Volumes
	AuditEventVolumeCreate = "Volume Create"
	AuditEventVolumeUpdate = "Volume Update"
	AuditEventVolumeDelete = "Volume Delete"

	// File storage buckets
	AuditEventBucketCreate   = "Bucket Create"
	AuditEventBucketDelete   = "Bucket Delete"
	AuditEventBucketShare    = "Bucket Share"
	AuditEventBucketUnshare  = "Bucket Unshare"
	AuditEventBucketTransfer = "Bucket Transfer"
	AuditEventBucketRename   = "Bucket Rename"

	// Backup and restore
	AuditEventBackup  = "Backup"
	AuditEventRestore = "Restore"

	// Scripts
	AuditEventScriptCreate  = "Script Create"
	AuditEventScriptUpdate  = "Script Update"
	AuditEventScriptDelete  = "Script Delete"
	AuditEventScriptExecute = "Script Execute"

	// Skills
	AuditEventSkillCreate = "Skill Create"
	AuditEventSkillUpdate = "Skill Update"
	AuditEventSkillDelete = "Skill Delete"

	// Slash Commands
	AuditEventSlashCommandCreate = "Slash Command Create"
	AuditEventSlashCommandUpdate = "Slash Command Update"
	AuditEventSlashCommandDelete = "Slash Command Delete"

	// MCP Servers
	AuditEventMCPServerCreate = "MCP Server Create"
	AuditEventMCPServerUpdate = "MCP Server Update"
	AuditEventMCPServerDelete = "MCP Server Delete"

	// Stack Definitions
	AuditEventStackDefCreate = "Stack Definition Create"
	AuditEventStackDefUpdate = "Stack Definition Update"
	AuditEventStackDefDelete = "Stack Definition Delete"

	// Stacks
	AuditEventStackStart   = "Stack Start"
	AuditEventStackStop    = "Stack Stop"
	AuditEventStackRestart = "Stack Restart"
	AuditEventStackDelete  = "Stack Delete"

	// Event Sinks
	AuditEventEventSinkCreate         = "Event Sink Create"
	AuditEventEventSinkUpdate         = "Event Sink Update"
	AuditEventEventSinkDelete         = "Event Sink Delete"
	AuditEventEventSinkDeliveryFailed = "Event Sink Delivery Failed"
	AuditEventEventSinkScriptFailed   = "Event Sink Script Failed"
	AuditEventEventSinkDropped        = "Event Sink Dropped"

	// Log sinks (Knot Pro) — a space registered to receive the logs of the
	// owner's other spaces
	AuditEventLogSinkRegister   = "Log Sink Register"
	AuditEventLogSinkDeregister = "Log Sink Deregister"

	// Space data access — gated by server.audit.file_operations. Paths and
	// byte counts only; file contents never enter the audit trail.
	AuditEventSpaceFileOp = "Space File Op"

	// Interactive access to a running space — gated by
	// server.audit.space_sessions.
	AuditEventSpaceSessionOpen = "Space Session Open"

	// API tokens (user-managed; OAuth flow tokens are not audited)
	AuditEventTokenCreate = "Token Create"
	AuditEventTokenUpdate = "Token Update"
	AuditEventTokenDelete = "Token Delete"

	// Runtime configuration changes
	AuditEventConfigUpdate = "Config Update"
)

Define events

View Source
const (
	PermissionManageUsers               = iota // Can Manage Users
	PermissionManageTemplates                  // Can Manage Templates
	PermissionManageSpaces                     // Can Manage Spaces
	PermissionManageVolumes                    // Can Manage Volumes
	PermissionManageGroups                     // Can Manage Groups
	PermissionManageRoles                      // Can Manage Roles
	PermissionManageVariables                  // Can Manage Variables
	PermissionUseSpaces                        // Can Use Spaces
	PermissionUseTunnels                       // Can Use Tunnels
	PermissionViewAuditLogs                    // Can View Audit Logs
	PermissionTransferSpaces                   // Can Transfer Spaces
	PermissionShareSpaces                      // Can Share Spaces
	PermissionClusterInfo                      // Can View Cluster Info
	PermissionUseVNC                           // Can use VNC
	PermissionUseWebTerminal                   // Can use the web terminal
	PermissionUseSSH                           // Can use ssh connections
	PermissionUseCodeServer                    // Can use code-server
	PermissionUseVSCodeTunnel                  // Can use VSCode Tunnel
	PermissionUseLogs                          // Can use the log window
	PermissionRunCommands                      // Can run commands in spaces
	PermissionCopyFiles                        // Can copy files to/from spaces
	PermissionUseMCPServer                     // Can use MCP server
	PermissionUseWebAssistant                  // Can use web-based AI assistant
	PermissionManageScripts                    // Can Manage System/Global Scripts
	PermissionExecuteScripts                   // Can Execute System/Global Scripts
	PermissionManageOwnScripts                 // Can Manage Own Scripts
	PermissionExecuteOwnScripts                // Can Execute Own Scripts
	PermissionManageGlobalSkills               // Can Manage Global Skills
	PermissionManageOwnSkills                  // Can Manage Own Skills
	PermissionSetSpaceDependencies             // Can configure space dependencies in the UI
	PermissionUseSpaceStartupScript            // Can configure user startup script in the space form UI
	PermissionDownloadAuditLogs                // Can Download Audit Logs
	PermissionManageStackDefinitions           // Can create/edit/delete global (system) stack definitions
	PermissionManageOwnStackDefinitions        // Can create/edit/delete personal stack definitions
	PermissionUseStackDefinitions              // Can create instances from stack definitions
	PermissionUseMethods                       // Can use shared space methods
	PermissionUsePools                         // Can use space pools
	PermissionManageEvents                     // Can Manage Own Event Sinks
	PermissionManageGlobalEvents               // Can Manage Global Event Sinks
	PermissionManageGlobalSlashCommands        // Can Manage Global Slash Commands
	PermissionManageOwnSlashCommands           // Can Manage Own Slash Commands
	PermissionManageMCPServers                 // Can Manage MCP Servers
	// PermissionUseLogSinks is enforced only by Knot Pro (spaces registering
	// as log sinks); the constant exists in both editions so the permission
	// ids stay aligned, but Core never grants or checks it.
	PermissionUseLogSinks // Can register a space as a log sink receiving own space logs
	// PermissionEditSpaceJobs gates editing job definitions (and the runner
	// toggle) on the user's own spaces; viewing them is always allowed.
	PermissionEditSpaceJobs // Can edit the scheduled jobs of own spaces
	PermissionViewPlugins   // Can View the plugins inventory
	// PermissionLinkUsers gates granting one user the ability to become
	// another (user manager): the linked accounts join its become-list
	// and its profile menu offers them. One way only. This is
	// impersonation-grade: whoever holds it can link to any account —
	// administrators included — and act as it fully.
	PermissionLinkUsers // Can link user accounts for fast user switching
	PermissionUseFiles  // Can use file storage: own buckets and buckets shared with them
	// PermissionManageFiles grants full access to every bucket, including
	// transferring a bucket to another owner.
	PermissionManageFiles // Can manage all file storage buckets
	// PermissionShareBuckets lets an owner share their buckets with users,
	// groups or everyone; PermissionTransferBuckets lets an owner give
	// their buckets to another user.
	PermissionShareBuckets    // Can share own buckets
	PermissionTransferBuckets // Can transfer own buckets to another user
	// PermissionBackup lets a user back up everything the server holds, every
	// user's files and credentials included, and restore it. It is root
	// equivalent and is not part of the Admin role: a new server gets a
	// Backup User role carrying it, which its first user is given.
	PermissionBackup // Can back up and restore the server
	// PermissionUseUserSecrets is enforced only by Knot Pro (resolving the
	// user's own 1Password secrets at runtime); the constant exists in both
	// editions so the permission ids stay aligned.
	PermissionUseUserSecrets // Can store a 1Password token and read own secrets
)

Permissions

View Source
const (
	RoleAdminUUID = "00000000-0000-0000-0000-000000000000"

	// BackupRoleName is the name of the role a new server creates for backups.
	BackupRoleName = "Backup User"
)

Roles

View Source
const (
	WebSessionCookie      = "__KNOT_WEBUI_SESSION"
	SessionExpiryDuration = 2 * time.Hour
)
View Source
const (
	SpaceFilesAll      = ""     // every bucket the owner can reach, as their shares allow
	SpaceFilesReadOnly = "ro"   // every bucket, read-only
	SpaceFilesNone     = "none" // no file storage at all
)

File storage modes of a restricted space.

View Source
const (
	SpaceUsageBucketMinute = "minute"
	SpaceUsageBucketDay    = "day"

	SpaceUsageMinuteRetention = 1 * time.Hour
	SpaceUsageDayRetention    = 7 * 24 * time.Hour
)
View Source
const (
	PlatformManual    = "manual"
	PlatformDocker    = "docker"
	PlatformPodman    = "podman"
	PlatformNomad     = "nomad"
	PlatformApple     = "apple"
	PlatformContainer = "container"
	PlatformKvm       = "kvm"

	KvmNetworkModeBridged = "bridged"
	KvmNetworkModeNat     = "nat"

	LeafNodeZone = "<leaf-node>"

	HealthCheckNone    = "none"
	HealthCheckAgent   = "agent"
	HealthCheckTCP     = "tcp"
	HealthCheckHTTP    = "http"
	HealthCheckProgram = "program"
	HealthCheckCustom  = "custom"
)
View Source
const (
	MaxTokenAge = 14 * 24 * time.Hour // 2 weeks

	// ScopeMethods allows a token to reach /api/methods* endpoints.
	// Scopes are narrowing: an empty/nil Scopes slice means unrestricted
	// (the token inherits the user's full authenticated surface, matching
	// pre-scopes behaviour). A non-empty slice restricts the token to only
	// the endpoint groups named by the listed scopes.
	ScopeMethods = "methods"
	ScopeMCP     = "mcp"
	// ScopeTunnels allows a token to reach the tunnel endpoints only:
	// the web/port tunnel websockets (/tunnel/*) and the user's tunnel
	// management API (/api/tunnels*). A tunnels-only key can create,
	// list and delete tunnels and nothing else, apart from reading its
	// own identity at /api/users/whoami (credential fields withheld),
	// which every scoped token may do.
	ScopeTunnels = "tunnels"
	// ScopeFiles allows a token to reach file storage: the files API
	// (/api/files*) and, on Knot Pro, the S3 endpoint with the token as the
	// secret key.
	ScopeFiles = "files"
	// ScopeBackup allows a token to reach the backup and restore endpoints
	// only, so a token left in a backup job can do nothing else.
	ScopeBackup = "backup"
)
View Source
const DefaultWebhookBodyTemplate = `` /* 147-byte string literal not displayed */
View Source
const PrefNavStarred = "nav.starred"

Preference keys stored under User.Preferences.

View Source
const TokenPrefix = "tk_"

TokenPrefix starts every API token, so a token is recognisable and never begins with "-", which a command line would read as another flag.

Variables

View Source
var AuditHook func(entry *AuditLogEntry)

AuditHook, when set, is invoked synchronously for every audit event — once on the server that emits it and, via cluster gossip, once on every peer that receives it — before the entry is routed or stored. It lives here (rather than in util/audit) so the service and cluster packages can tap the stream without an import cycle. Implementations must be fast, and must skip the events they generate themselves (e.g. AuditEventAnomalyDetected) or they will recurse. Used by Knot Pro to run anomaly detection over the cluster-wide audit stream.

KnownTokenScopes is the authoritative list of valid scope strings.

View Source
var PermissionNames = []PermissionName{
	{PermissionViewAuditLogs, "Audit", "View Audit Logs", "View the audit log of system activity."},
	{PermissionDownloadAuditLogs, "Audit", "Download Audit Logs", "Export audit log entries to a file."},

	{PermissionClusterInfo, "System", "View Cluster Info", "View cluster node and topology information."},
	{PermissionViewPlugins, "System", "View Plugins", "View the loaded plugins inventory."},
	{PermissionBackup, "System", "Backup Server", "Back up all of the server's data, including every user's files and credentials, and restore it. Equivalent to full access: not part of the Admin role."},

	{PermissionManageGroups, "User Management", "Manage Groups", "Create, edit, and delete user groups."},
	{PermissionManageRoles, "User Management", "Manage Roles", "Create, edit, and delete roles and their permissions."},
	{PermissionManageUsers, "User Management", "Manage Users", "Create, edit, and delete user accounts."},
	{PermissionLinkUsers, "User Management", "Link Users", "Grant one user the ability to switch into another account from the profile menu. Treat as impersonation-grade."},

	{PermissionManageSpaces, "Resource Management", "Manage Spaces", "Manage any space, including those owned by other users."},
	{PermissionManageTemplates, "Resource Management", "Manage Templates", "Create, edit, and delete space templates."},
	{PermissionManageVariables, "Resource Management", "Manage Variables", "Create, edit, and delete system variables."},
	{PermissionManageVolumes, "Resource Management", "Manage Volumes", "Create, edit, and delete volumes."},

	{PermissionUseFiles, "File Storage", "Use File Storage", "Create and delete own buckets and manage their files."},
	{PermissionShareBuckets, "File Storage", "Share Buckets", "Share own buckets with users, groups or everyone."},
	{PermissionTransferBuckets, "File Storage", "Transfer Buckets", "Transfer own buckets to another user."},
	{PermissionManageFiles, "File Storage", "Manage File Storage", "Full access to every bucket, including sharing and transferring any bucket."},

	{PermissionUseMCPServer, "AI Tools", "Use MCP Server", "Connect to the knot MCP server."},
	{PermissionUseWebAssistant, "AI Tools", "Use Web Assistant", "Use the built-in web AI assistant."},

	{PermissionManageScripts, "Scripting", "Manage System Scripts", "Create and edit system (global) scripts."},
	{PermissionExecuteScripts, "Scripting", "Execute System Scripts", "Run system (global) scripts."},
	{PermissionManageOwnScripts, "Scripting", "Manage Own Scripts", "Create and edit your own scripts."},
	{PermissionExecuteOwnScripts, "Scripting", "Execute Own Scripts", "Run your own scripts."},

	{PermissionManageEvents, "Events", "Manage Own Event Sinks", "Create and manage your own event sinks."},
	{PermissionManageGlobalEvents, "Events", "Manage Global Event Sinks", "Create and manage global event sinks."},

	{PermissionManageGlobalSkills, "Skills", "Manage Global Skills", "Create and edit global skills."},
	{PermissionManageOwnSkills, "Skills", "Manage Own Skills", "Create and edit your own skills."},

	{PermissionManageGlobalSlashCommands, "Slash Commands", "Manage Global Slash Commands", "Create and edit global slash commands."},
	{PermissionManageOwnSlashCommands, "Slash Commands", "Manage Own Slash Commands", "Create and edit your own slash commands."},

	{PermissionManageMCPServers, "AI Tools", "Manage MCP Servers", "Register and configure MCP servers."},

	{PermissionManageStackDefinitions, "Stacks", "Manage Global Stack Definitions", "Create, edit, and delete global (system) stack definitions."},
	{PermissionManageOwnStackDefinitions, "Stacks", "Manage Own Stack Definitions", "Create, edit, and delete personal stack definitions."},
	{PermissionUseStackDefinitions, "Stacks", "Use Stack Definitions", "Create spaces from stack definitions."},

	{PermissionUseMethods, "Methods", "Use Space Methods Shared by Others", "Call space methods shared by other users."},

	{PermissionUseTunnels, "Public Tunnels", "Use Tunnels", "Expose a local or space port as a public URL via a knot tunnel."},

	{PermissionUseSpaces, "Space Operations", "Use Spaces", "Create and run spaces."},
	{PermissionUsePools, "Space Operations", "Use Space Pools", "Create and run space pools."},
	{PermissionSetSpaceDependencies, "Space Operations", "Set Space Dependencies", "Configure dependencies between spaces."},
	{PermissionEditSpaceJobs, "Space Operations", "Edit Space Jobs", "Edit the scheduled jobs of your own spaces."},
	{PermissionUseSpaceStartupScript, "Space Operations", "Use User Startup Script", "Set a user startup script that runs when a space starts."},
	{PermissionShareSpaces, "Space Operations", "Share Spaces", "Share your spaces with other users."},
	{PermissionTransferSpaces, "Space Operations", "Transfer Spaces", "Transfer ownership of your spaces to another user."},
	{PermissionUseCodeServer, "Space Operations", "Use Code Server", "Open code-server in a space."},
	{PermissionUseLogs, "Space Operations", "View Logs", "View the log window for a space."},
	{PermissionUseSSH, "Space Operations", "Use SSH", "Connect to spaces over SSH."},
	{PermissionUseVNC, "Space Operations", "Use VNC", "Use the VNC graphical desktop in a space."},
	{PermissionUseVSCodeTunnel, "Space Operations", "Use VSCode Tunnel", "Connect to a space via a VS Code tunnel."},
	{PermissionUseWebTerminal, "Space Operations", "Use Web Terminal", "Use the web terminal in a space."},
	{PermissionRunCommands, "Space Operations", "Run Commands", "Execute commands inside a space."},
	{PermissionCopyFiles, "Space Operations", "Copy Files", "Copy files to and from a space."},
}

Functions

func BackendEnabled added in v0.35.0

func BackendEnabled(platform string, enabled []string) bool

BackendEnabled reports whether a platform is offered by the server's enabled-backends allowlist. An empty list means everything is offered (manual included); a non-empty list must name a platform to offer it, manual included. The "container" platform (auto-detect) is offered when any container runtime is.

func BucketStartForKind added in v0.24.0

func BucketStartForKind(bucketStart time.Time, bucketKind string) time.Time

func DeleteRoleFromCache

func DeleteRoleFromCache(roleId string)

func FilterVars

func FilterVars(variables []*TemplateVar) map[string]interface{}

func GetUserPermissions added in v0.23.0

func GetUserPermissions(user *User) []uint16

GetUserPermissions returns all permission integers for a user (resolves from roles)

func IsBuiltinRole added in v0.37.0

func IsBuiltinRole(id string) bool

IsBuiltinRole reports whether a role is built in: it can't be edited or deleted.

func IsKnownTokenScope added in v0.28.0

func IsKnownTokenScope(s string) bool

IsKnownTokenScope reports whether s is a valid scope string.

func LinkUsers added in v0.34.0

func LinkUsers(user, other *User) bool

LinkUsers adds other to user's become-list: user may switch its session to other, never the other way around. Returns false when the link already exists or either side is missing; the caller persists user.

func MissingRequiredCustomFields added in v0.34.0

func MissingRequiredCustomFields(template *Template, provided []SpaceCustomField) []string

MissingRequiredCustomFields returns the names of the template's required custom fields the provided values leave blank — absent, empty, or whitespace-only. A default can satisfy a requirement, so callers run it after ApplyCustomFieldDefaults. A bool field is never blank (it is always "true" or "false").

func NormalizeSpaceUsageBucketKind added in v0.24.0

func NormalizeSpaceUsageBucketKind(bucketKind string) string

func PermissionKey added in v0.34.0

func PermissionKey(id uint16) string

permissionKeys maps each built-in permission constant to its stable snake_case key — the machine identifier plugins check (user.has_permission("manage_spaces")). Display names are for humans and may be reworded; keys never change. The keysComplete test fails when a new permission ships without a key. PermissionKey returns the stable snake_case key for a built-in permission id, or "" when unknown.

func RenderEventTemplate added in v0.28.0

func RenderEventTemplate(bodyTemplate string, data *EventRenderData) ([]byte, error)

func RequestProperties added in v0.24.0

func RequestProperties(r *http.Request, properties *map[string]interface{}) *map[string]interface{}

RequestProperties extracts source_ip and user_agent from an HTTP request and merges them into an existing properties map, or creates a new one.

func ResolveVariables

func ResolveVariables(srcString string, t *Template, space *Space, user *User, variables map[string]interface{}) (string, error)

Parse an input string and resolve knot variables

func RoleExists

func RoleExists(roleId string) bool

func RoleName added in v0.33.0

func RoleName(roleId string) string

RoleName resolves a role id to its cached name, falling back to the id for unknown roles (e.g. audit entries emitted before the cache was warm).

func RoleNames added in v0.33.0

func RoleNames(roleIds []string) []string

RoleNames resolves role ids to cached names for audit properties.

func SaveRoleToCache

func SaveRoleToCache(role *Role)

func SetRoleCache

func SetRoleCache(roles []*Role)

func SetStackResolver added in v0.30.1

func SetStackResolver(f func(space *Space, variables map[string]interface{}) map[string]interface{})

SetStackResolver registers the function used to resolve .stack.* template variables. Intended to be called once at server startup.

func SpaceUsageRetentionForKind added in v0.24.0

func SpaceUsageRetentionForKind(bucketKind string) time.Duration

func SpaceUsageSampleIdForKind added in v0.24.0

func SpaceUsageSampleIdForKind(spaceId, bucketKind string, bucketStart time.Time) string

func UnlinkUser added in v0.34.0

func UnlinkUser(user, other *User)

UnlinkUser removes other from user's become-list; other's own list is untouched — links were only ever one way. The caller persists user.

func ValidSpaceFilesMode added in v0.40.0

func ValidSpaceFilesMode(mode string) bool

ValidSpaceFilesMode reports whether mode is a known file storage mode.

Types

type AltNameEntry added in v0.25.0

type AltNameEntry struct {
	Name string `json:"name"`
	Port uint16 `json:"port"`
}

func (*AltNameEntry) Scan added in v0.25.0

func (a *AltNameEntry) Scan(value interface{}) error

Scan implements the sql.Scanner interface.

func (AltNameEntry) Value added in v0.25.0

func (a AltNameEntry) Value() (driver.Value, error)

Value implements the driver.Valuer interface.

type AuditLogEntry

type AuditLogEntry struct {
	Id         int64                  `json:"audit_log_id" db:"audit_log_id,pk"`
	Zone       string                 `json:"zone" db:"zone"`
	Actor      string                 `json:"actor" db:"actor"`
	ActorType  string                 `json:"actor_type" db:"actor_type"`
	Event      string                 `json:"event" db:"event"`
	When       time.Time              `json:"created_at" db:"created_at"`
	Details    string                 `json:"details" db:"details"`
	Properties map[string]interface{} `json:"properties" db:"properties,json"`
}

func NewAuditLogEntry

func NewAuditLogEntry(actor, actorType, event, details string, properties *map[string]interface{}) *AuditLogEntry

func (*AuditLogEntry) MatchesFilter added in v0.24.0

func (e *AuditLogEntry) MatchesFilter(filter *AuditLogFilter) bool

MatchesFilter returns true if the entry matches the given filter criteria.

type AuditLogFilter added in v0.24.0

type AuditLogFilter struct {
	Query     string
	Actor     string
	ActorType string
	Event     string
	From      *time.Time
	To        *time.Time
}

type CSIVolume

type CSIVolume struct {
	Id           string                `yaml:"id" json:"ID"`
	Name         string                `yaml:"name" json:"Name"`
	Namespace    string                `yaml:"namespace" json:"Namespace"`
	PuluginId    string                `yaml:"plugin_id" json:"PluginID"`
	Type         string                `yaml:"type" json:"Type"`
	MountOptions CSIVolumeMountOptions `yaml:"mount_options" json:"MountOptions"`
	CapacityMin  interface{}           `yaml:"capacity_min,omitempty" json:"RequestedCapacityMin,omitempty"`
	CapacityMax  interface{}           `yaml:"capacity_max,omitempty" json:"RequestedCapacityMax,omitempty"`
	Capabilities []CSIVolumeCapability `yaml:"capabilities,omitempty" json:"RequestedCapabilities,omitempty"`
	Secrets      map[string]string     `yaml:"secrets,omitempty" json:"Secrets,omitempty"`
	Parameters   map[string]string     `yaml:"parameters,omitempty" json:"Parameters,omitempty"`
}

type CSIVolumeCapability

type CSIVolumeCapability struct {
	AccessMode     string `yaml:"access_mode" json:"AccessMode"`
	AttachmentMode string `yaml:"attachment_mode" json:"AttachmentMode"`
}

type CSIVolumeMountOptions

type CSIVolumeMountOptions struct {
	FsType     string   `yaml:"fs_type" json:"FsType"`
	MountFlags []string `yaml:"mount_flags" json:"MountFlags"`
}

type CSIVolumes

type CSIVolumes struct {
	Volumes []CSIVolume `yaml:"volumes" json:"Volumes"`
}

func LoadVolumesFromYaml

func LoadVolumesFromYaml(yamlData string, t *Template, space *Space, user *User, variables map[string]interface{}) (*CSIVolumes, error)

type CfgValue

type CfgValue struct {
	Name  string `json:"name" db:"name,pk" msgpack:"name"`
	Value string `json:"value" db:"value" msgpack:"value"`
}

CfgValue object

type Command added in v0.29.0

type Command struct {
	Id            string        `json:"command_id" db:"command_id,pk"`
	UserId        string        `json:"user_id" db:"user_id"`
	Name          string        `json:"name" db:"name"`
	Description   string        `json:"description" db:"description"`
	ArgumentHint  string        `json:"argument_hint" db:"argument_hint"`
	AllowedTools  []string      `json:"allowed_tools" db:"allowed_tools,json"`
	Body          string        `json:"body" db:"body"`
	Groups        []string      `json:"groups" db:"groups,json"`
	Zones         []string      `json:"zones" db:"zones,json"`
	Active        bool          `json:"active" db:"active"`
	IsDeleted     bool          `json:"is_deleted" db:"is_deleted"`
	IsManaged     bool          `json:"is_managed" db:"is_managed"`
	CreatedUserId string        `json:"created_user_id" db:"created_user_id"`
	CreatedAt     time.Time     `json:"created_at" db:"created_at"`
	UpdatedUserId string        `json:"updated_user_id" db:"updated_user_id"`
	UpdatedAt     hlc.Timestamp `json:"updated_at" db:"updated_at"`
}

Command is a user-invokable slash command stored in the database. Mirrors the shape of a lmchatkit slash-command markdown file (name, description, argument-hint, allowed-tools, body) plus the ownership/ACL fields used by knot (UserId for user/global, Groups, Zones, Active). The Body is the raw markdown with an optional $ARGUMENTS placeholder substituted at render time.

func NewCommand added in v0.29.0

func NewCommand(
	name string,
	description string,
	argumentHint string,
	allowedTools []string,
	body string,
	groups []string,
	zones []string,
	ownerUserId string,
	createdUserId string,
) *Command

func (*Command) IsGlobalCommand added in v0.29.0

func (command *Command) IsGlobalCommand() bool

func (*Command) IsUserCommand added in v0.29.0

func (command *Command) IsUserCommand() bool

func (*Command) IsValidForZone added in v0.29.0

func (command *Command) IsValidForZone(zone string) bool

type Conversation added in v0.29.0

type Conversation struct {
	Id        string        `json:"conversation_id" db:"conversation_id,pk" msgpack:"conversation_id"`
	UserId    string        `json:"user_id" db:"user_id" msgpack:"user_id"`
	Title     string        `json:"title" db:"title" msgpack:"title"`
	Data      string        `json:"data" db:"data" msgpack:"data"`
	CreatedAt time.Time     `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedAt hlc.Timestamp `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
	IsDeleted bool          `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
}

Conversation is a stored chat conversation (server-side chat history).

It is owned by a single user (UserId) and holds the full lmchatkit StoredConversation (summary + messages) as an opaque JSON blob in Data — the HistoryStore implementation (internal/lmchatkit) owns the encoding, so this package stays free of any lmchatkit dependency.

UpdatedAt is a hybrid-logical-clock timestamp used for gossip conflict resolution between cluster servers (the newest copy wins). IsDeleted is a soft-delete tombstone that is itself gossiped, so a late-arriving save can never resurrect a conversation the user deleted.

type EventRenderData added in v0.28.0

type EventRenderData struct {
	EventId      string
	EventType    string
	SpaceId      string
	SpaceName    string
	UserId       string
	Username     string
	PoolName     string
	PortURLs     map[string]string
	CustomFields map[string]string
	Payload      map[string]interface{}
	Ts           hlc.Timestamp
	ActorId      string
	ActorName    string
	ActorKind    string
}

type EventSink added in v0.28.0

type EventSink struct {
	Id            string         `json:"event_sink_id" db:"event_sink_id,pk" msgpack:"event_sink_id"`
	UserId        string         `json:"user_id" db:"user_id" msgpack:"user_id"`
	Name          string         `json:"name" db:"name" msgpack:"name"`
	Description   string         `json:"description" db:"description" msgpack:"description"`
	Events        []string       `json:"events" db:"events,json" msgpack:"events"`
	SinkType      string         `json:"sink_type" db:"sink_type" msgpack:"sink_type"`
	Webhook       *WebhookConfig `json:"webhook,omitempty" db:"webhook,json" msgpack:"webhook,omitempty"`
	ScriptId      string         `json:"script_id,omitempty" db:"script_id" msgpack:"script_id,omitempty"`
	Active        bool           `json:"active" db:"active" msgpack:"active"`
	CreatedUserId string         `json:"created_user_id" db:"created_user_id" msgpack:"created_user_id"`
	CreatedAt     time.Time      `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedUserId string         `json:"updated_user_id" db:"updated_user_id" msgpack:"updated_user_id"`
	UpdatedAt     hlc.Timestamp  `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
	IsDeleted     bool           `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
}

func NewEventSink added in v0.28.0

func NewEventSink(name, description string, events []string, sinkType string, webhook *WebhookConfig, scriptId string, active bool, ownerUserId, createdUserId string) *EventSink

func (*EventSink) IsGlobalSink added in v0.28.0

func (s *EventSink) IsGlobalSink() bool

func (*EventSink) MatchEventType added in v0.28.0

func (s *EventSink) MatchEventType(eventType string) bool

MatchEventType tests if an event type matches any of the sink's patterns.

type ExternalProvider added in v0.23.7

type ExternalProvider struct {
	ProviderUID  string `json:"provider_uid"`            // provider's own stable user ID (e.g. GitHub integer ID)
	Username     string `json:"username"`                // human-readable handle, may change
	Token        string `json:"token"`                   // encrypted access token
	RefreshToken string `json:"refresh_token,omitempty"` // encrypted refresh token
}

ExternalProvider holds the identity and token for a linked OAuth provider.

type Group

type Group struct {
	Id            string        `json:"group_id" db:"group_id,pk" msgpack:"group_id"`
	Name          string        `json:"name" db:"name" msgpack:"name"`
	MaxSpaces     uint32        `json:"max_spaces" db:"max_spaces" msgpack:"max_spaces"`
	ComputeUnits  uint32        `json:"compute_units" db:"compute_units" msgpack:"compute_units"`
	StorageUnits  uint32        `json:"storage_units" db:"storage_units" msgpack:"storage_units"`
	MaxTunnels    uint32        `json:"max_tunnels" db:"max_tunnels" msgpack:"max_tunnels"`
	FileStorageMB uint32        `json:"file_storage_mb" db:"file_storage_mb" msgpack:"file_storage_mb"`
	MaxBuckets    uint32        `json:"max_buckets" db:"max_buckets" msgpack:"max_buckets"`
	IsDeleted     bool          `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
	CreatedUserId string        `json:"created_user_id" db:"created_user_id" msgpack:"created_user_id"`
	CreatedAt     time.Time     `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedUserId string        `json:"updated_user_id" db:"updated_user_id" msgpack:"updated_user_id"`
	UpdatedAt     hlc.Timestamp `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
}

Group object

func NewGroup

func NewGroup(name string, userId string, maxSpaces uint32, computeUnits uint32, storageUnits uint32, maxTunnels uint32) *Group

type KvmNetwork added in v0.35.0

type KvmNetwork struct {
	IPNet   *net.IPNet
	Start   net.IP
	End     net.IP
	Gateway net.IP
}

KvmNetwork is the parsed and validated form of a template's KVM network fields: the subnet VMs are attached to and the address range spaces pick their IP from.

func ParseKvmNetwork added in v0.35.0

func ParseKvmNetwork(template *Template) (*KvmNetwork, error)

ParseKvmNetwork validates a template's KVM network configuration. All fields must be present and consistent: CIDR parseable, the range inside the subnet with start <= end, and the optional gateway inside the subnet (it defaults to the network's first usable address).

func (*KvmNetwork) Broadcast added in v0.35.0

func (n *KvmNetwork) Broadcast() net.IP

Broadcast returns the subnet's broadcast address.

func (*KvmNetwork) Range added in v0.35.0

func (n *KvmNetwork) Range() (net.IP, net.IP)

Range returns the effective pick range: the configured start/end, or the network's whole usable address space when no range is set.

func (*KvmNetwork) ValidateSpaceIP added in v0.35.0

func (n *KvmNetwork) ValidateSpaceIP(ipStr string) error

ValidateSpaceIP checks that ip is a usable address for a space's VM: valid IPv4, inside the configured range, and not the network, broadcast or gateway address.

type LocalStorageSpec added in v0.25.0

type LocalStorageSpec struct {
	Volumes map[string]LocalVolumeEntry `yaml:"volumes"`
	Paths   PathList                    `yaml:"paths"`
}

func LoadLocalStorageFromYaml added in v0.25.0

func LoadLocalStorageFromYaml(yamlData string, t *Template, space *Space, user *User, variables map[string]interface{}) (*LocalStorageSpec, error)

type LocalVolumeEntry added in v0.25.0

type LocalVolumeEntry struct {
	Size string `yaml:"size,omitempty"`
}

type MCPServer added in v0.29.0

type MCPServer struct {
	Id                string        `json:"mcp_server_id" db:"mcp_server_id,pk" msgpack:"mcp_server_id"`
	UserId            string        `json:"user_id" db:"user_id" msgpack:"user_id"`
	Namespace         string        `json:"namespace" db:"namespace" msgpack:"namespace"`
	URL               string        `json:"url" db:"url" msgpack:"url"`
	Command           string        `json:"command" db:"command" msgpack:"command"`
	Args              []string      `json:"args" db:"args,json" msgpack:"args"`
	Env               []string      `json:"env" db:"env,json" msgpack:"env"`
	AuthType          string        `json:"auth_type" db:"auth_type" msgpack:"auth_type"`
	Token             string        `json:"token" db:"token" msgpack:"token"`
	OAuthClientID     string        `json:"oauth_client_id" db:"oauth_client_id" msgpack:"oauth_client_id"`
	OAuthTokenURL     string        `json:"oauth_token_url" db:"oauth_token_url" msgpack:"oauth_token_url"`
	OAuthAccessToken  string        `json:"oauth_access_token" db:"oauth_access_token" msgpack:"oauth_access_token"`
	OAuthRefreshToken string        `json:"oauth_refresh_token" db:"oauth_refresh_token" msgpack:"oauth_refresh_token"`
	Enabled           bool          `json:"enabled" db:"enabled" msgpack:"enabled"`
	ToolVisibility    string        `json:"tool_visibility" db:"tool_visibility" msgpack:"tool_visibility"`
	DisabledTools     []string      `json:"disabled_tools" db:"disabled_tools,json" msgpack:"disabled_tools"`
	RemoteSearch      bool          `json:"remote_search" db:"remote_search" msgpack:"remote_search"`
	IsDeleted         bool          `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
	CreatedUserId     string        `json:"created_user_id" db:"created_user_id" msgpack:"created_user_id"`
	CreatedAt         time.Time     `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedUserId     string        `json:"updated_user_id" db:"updated_user_id" msgpack:"updated_user_id"`
	UpdatedAt         hlc.Timestamp `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
}

func NewMCPServer added in v0.29.0

func NewMCPServer(
	namespace string,
	ownerUserId string,
	createdUserId string,
) *MCPServer

func (*MCPServer) IsToolEnabled added in v0.29.0

func (s *MCPServer) IsToolEnabled(toolName string) bool

IsToolEnabled checks if a specific tool is enabled for this server. A tool is enabled unless it appears in the DisabledTools list.

func (*MCPServer) IsUserServer added in v0.29.0

func (s *MCPServer) IsUserServer() bool

type ManagedPathsSpec added in v0.25.0

type ManagedPathsSpec struct {
	Paths PathList `yaml:"paths"`
}

func LoadManagedPathsFromYaml added in v0.25.0

func LoadManagedPathsFromYaml(yamlData string, t *Template, space *Space, user *User, variables map[string]interface{}) (*ManagedPathsSpec, error)
type NavPage struct {
	URL   string
	Label string
}

NavPage is a sidebar navigation destination (a page), without any icon or top/More grouping — just enough for the global-search "pages" group.

func VisibleNavPages added in v0.32.0

func VisibleNavPages(user *User, cfg *config.ServerConfig, auditAvailable, pluginsAvailable bool) []NavPage

VisibleNavPages returns the sidebar pages the given user may see, in sidebar order. The visibility gates mirror web/nav.go buildNav exactly (combined across the top and "More" sections), so a page appears here iff it appears in the user's menu. auditAvailable is whether the audit-log feature is usable in this deployment (storage present + not routed externally), and pluginsAvailable whether the plugins path produced anything — both passed in so this function stays pure and testable.

type PathList added in v0.25.0

type PathList []string

func (*PathList) UnmarshalYAML added in v0.25.0

func (paths *PathList) UnmarshalYAML(value *yaml.Node) error

type PermissionName

type PermissionName struct {
	Id          int    `json:"id"`
	Group       string `json:"group"`
	Name        string `json:"name"`
	Description string `json:"description"`
}

type PoolDefinition added in v0.28.0

type PoolDefinition struct {
	Id              string `json:"pool_id" db:"pool_id,pk" msgpack:"pool_id"`
	Name            string `json:"name" db:"name" msgpack:"name"`
	TemplateId      string `json:"template_id" db:"template_id" msgpack:"template_id"`
	StartupScriptId string `json:"startup_script_id" db:"startup_script_id" msgpack:"startup_script_id"`
	DesiredCount    int    `json:"desired_count" db:"desired_count" msgpack:"desired_count"`
	Active          bool   `json:"active" db:"active" msgpack:"active"`
	Zone            string `json:"zone" db:"zone" msgpack:"zone"`
	IsDeleted       bool   `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
	// Exclusive member leases. LeaseMaxTime is in seconds: 0 = leases
	// disabled (the default), -1 = no timeout (leases run until released),
	// >0 = maximum duration of one acquire/extend. LeaseMaxExtensions:
	// 0 = extending forbidden, -1 = unlimited, >0 = max extensions per lease.
	LeaseMaxTime       int `json:"lease_max_time" db:"lease_max_time" msgpack:"lease_max_time"`
	LeaseMaxExtensions int `json:"lease_max_extensions" db:"lease_max_extensions" msgpack:"lease_max_extensions"`
	// Custom field values given to every member. Copied onto a member when
	// it is created or started, so a change reaches running members on
	// their next start.
	CustomFields  []SpaceCustomField `json:"custom_fields" db:"custom_fields,json" msgpack:"custom_fields"`
	CreatedUserId string             `json:"created_user_id" db:"created_user_id" msgpack:"created_user_id"`
	CreatedAt     time.Time          `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedUserId string             `json:"updated_user_id" db:"updated_user_id" msgpack:"updated_user_id"`
	UpdatedAt     hlc.Timestamp      `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
}

func NewPoolDefinition added in v0.28.0

func NewPoolDefinition(name, templateId, startupScriptId string, desiredCount int, userId string) *PoolDefinition

func (*PoolDefinition) LeaseDuration added in v0.36.0

func (p *PoolDefinition) LeaseDuration() (time.Duration, bool)

LeaseDuration converts the pool's LeaseMaxTime into a time.Duration. The second return value reports whether leases are enabled at all.

type PortForwardEntry added in v0.24.0

type PortForwardEntry struct {
	LocalPort  uint16 `json:"local_port" yaml:"local_port"`
	Space      string `json:"space" yaml:"space"`
	RemotePort uint16 `json:"remote_port" yaml:"remote_port"`
}

func (*PortForwardEntry) Scan added in v0.24.0

func (pf *PortForwardEntry) Scan(value interface{}) error

Scan implements the sql.Scanner interface.

func (PortForwardEntry) Value added in v0.24.0

func (pf PortForwardEntry) Value() (driver.Value, error)

Value implements the driver.Valuer interface.

type Quota

type Quota struct {
	ComputeUnits  uint32
	StorageUnits  uint32
	MaxSpaces     uint32
	MaxTunnels    uint32
	FileStorageMB uint32
	MaxBuckets    uint32
}

type Response added in v0.23.0

type Response struct {
	Id                 string                 `json:"response_id" db:"response_id,pk" msgpack:"response_id"`
	Status             ResponseStatus         `json:"status" db:"status" msgpack:"status"`
	Request            map[string]interface{} `json:"request" db:"request,json" msgpack:"request"`
	Response           map[string]interface{} `json:"response" db:"response,json" msgpack:"response"`
	Error              string                 `json:"error,omitempty" db:"error_text" msgpack:"error"`
	PreviousResponseId string                 `json:"previous_response_id,omitempty" db:"previous_response_id" msgpack:"previous_response_id"`
	UserId             string                 `json:"user_id" db:"user_id" msgpack:"user_id"`
	SpaceId            string                 `json:"space_id,omitempty" db:"space_id" msgpack:"space_id"`
	ExpiresAt          *time.Time             `json:"expires_at,omitempty" db:"expires_at" msgpack:"expires_at"`
	IsDeleted          bool                   `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
	CreatedAt          time.Time              `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedAt          hlc.Timestamp          `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
}

Response object for OpenAI Responses API

func NewResponse added in v0.23.0

func NewResponse(userId string, spaceId string, ttl time.Duration) *Response

NewResponse creates a new Response object

func (*Response) GetRequest added in v0.23.0

func (r *Response) GetRequest(data interface{}) error

GetRequest populates the request data into a structure

func (*Response) GetResponse added in v0.23.0

func (r *Response) GetResponse(data interface{}) error

GetResponse populates the response data into a structure

func (*Response) SetRequest added in v0.23.0

func (r *Response) SetRequest(data interface{}) error

SetRequest sets the request data from a JSON-serializable structure

func (*Response) SetResponse added in v0.23.0

func (r *Response) SetResponse(data interface{}) error

SetResponse sets the response data from a JSON-serializable structure

type ResponseStatus added in v0.23.0

type ResponseStatus string

ResponseStatus represents the status of a response

const (
	StatusPending    ResponseStatus = "pending"
	StatusInProgress ResponseStatus = "in_progress"
	StatusCompleted  ResponseStatus = "completed"
	StatusCancelled  ResponseStatus = "cancelled"
	StatusFailed     ResponseStatus = "failed"
)

type Role

type Role struct {
	Id                string        `json:"role_id" db:"role_id,pk" msgpack:"role_id"`
	Name              string        `json:"name" db:"name" msgpack:"name"`
	Permissions       []uint16      `json:"permissions" db:"permissions,json" msgpack:"permissions"`
	PluginPermissions []string      `json:"plugin_permissions" db:"plugin_permissions,json" msgpack:"plugin_permissions"`
	IsDeleted         bool          `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
	CreatedUserId     string        `json:"created_user_id" db:"created_user_id" msgpack:"created_user_id"`
	CreatedAt         time.Time     `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedUserId     string        `json:"updated_user_id" db:"updated_user_id" msgpack:"updated_user_id"`
	UpdatedAt         hlc.Timestamp `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
}

Role

func GetRolesFromCache

func GetRolesFromCache() []*Role

func NewRole

func NewRole(name string, permissions []uint16, userId string) *Role

type Script added in v0.23.0

type Script struct {
	Id                 string        `json:"script_id" db:"script_id,pk"`
	UserId             string        `json:"user_id" db:"user_id"`
	Name               string        `json:"name" db:"name"`
	Description        string        `json:"description" db:"description"`
	Content            string        `json:"content" db:"content"`
	Groups             []string      `json:"groups" db:"groups,json"`
	Zones              []string      `json:"zones" db:"zones,json"`
	Active             bool          `json:"active" db:"active"`
	ScriptType         string        `json:"script_type" db:"script_type"`
	MCPInputSchemaToml string        `json:"mcp_input_schema_toml" db:"mcp_input_schema_toml"`
	MCPKeywords        []string      `json:"mcp_keywords" db:"mcp_keywords,json"`
	Discoverable       bool          `json:"discoverable" db:"discoverable"`
	IsDeleted          bool          `json:"is_deleted" db:"is_deleted"`
	IsManaged          bool          `json:"is_managed" db:"is_managed"`
	CreatedUserId      string        `json:"created_user_id" db:"created_user_id"`
	CreatedAt          time.Time     `json:"created_at" db:"created_at"`
	UpdatedUserId      string        `json:"updated_user_id" db:"updated_user_id"`
	UpdatedAt          hlc.Timestamp `json:"updated_at" db:"updated_at"`
}

func NewScript added in v0.23.0

func NewScript(
	name string,
	description string,
	content string,
	groups []string,
	zones []string,
	active bool,
	scriptType string,
	mcpInputSchemaToml string,
	mcpKeywords []string,
	discoverable bool,
	ownerUserId string,
	createdUserId string,
) *Script

func (*Script) IsGlobalScript added in v0.23.0

func (script *Script) IsGlobalScript() bool

IsGlobalScript returns true if the script is a system/global script (UserId is empty)

func (*Script) IsUserScript added in v0.23.0

func (script *Script) IsUserScript() bool

IsUserScript returns true if the script is a user script (UserId is not empty)

func (*Script) IsValidForZone added in v0.23.0

func (script *Script) IsValidForZone(zone string) bool

IsValidForZone determines whether the script is valid for execution in the specified zone. The function evaluates zone restrictions based on the script's Zones configuration. If no zones are specified, the script is considered valid for all zones (global). Zone names prefixed with '!' are treated as exclusions (negated zones). The function first checks for exclusions, then checks for explicit inclusions.

zone is the target zone name to validate against the script's zone restrictions.

Returns true if the script can be executed in the specified zone, false otherwise.

type Session

type Session struct {
	Id string `json:"session_id" db:"session_id,pk"`
	Ip string `json:"ip" db:"ip"`
	// UserId is the account the session currently runs as. Switching user
	// rewrites it; OriginalUserId keeps the account that actually
	// authenticated so the session can always flick back — fast user
	// switching, with no reverse link granted.
	UserId         string        `json:"user_id" db:"user_id"`
	OriginalUserId string        `json:"original_user_id" db:"original_user_id"`
	UserAgent      string        `json:"user_agent" db:"user_agent"`
	ExpiresAfter   time.Time     `json:"expires_after" db:"expires_after"`
	UpdatedAt      hlc.Timestamp `json:"updated_at" db:"updated_at"`
	IsDeleted      bool          `json:"is_deleted" db:"is_deleted"`
}

Session object

func NewSession

func NewSession(r *http.Request, userId string) *Session

type Skill added in v0.23.0

type Skill struct {
	Id            string        `json:"skill_id" db:"skill_id,pk"`
	UserId        string        `json:"user_id" db:"user_id"`
	Name          string        `json:"name" db:"name"`
	Description   string        `json:"description" db:"description"`
	Content       string        `json:"content" db:"content"`
	Groups        []string      `json:"groups" db:"groups,json"`
	Zones         []string      `json:"zones" db:"zones,json"`
	Active        bool          `json:"active" db:"active"`
	IsDeleted     bool          `json:"is_deleted" db:"is_deleted"`
	IsManaged     bool          `json:"is_managed" db:"is_managed"`
	CreatedUserId string        `json:"created_user_id" db:"created_user_id"`
	CreatedAt     time.Time     `json:"created_at" db:"created_at"`
	UpdatedUserId string        `json:"updated_user_id" db:"updated_user_id"`
	UpdatedAt     hlc.Timestamp `json:"updated_at" db:"updated_at"`
}

func NewSkill added in v0.23.0

func NewSkill(
	name string,
	description string,
	content string,
	groups []string,
	zones []string,
	ownerUserId string,
	createdUserId string,
) *Skill

func (*Skill) IsGlobalSkill added in v0.23.0

func (skill *Skill) IsGlobalSkill() bool

func (*Skill) IsUserSkill added in v0.23.0

func (skill *Skill) IsUserSkill() bool

func (*Skill) IsValidForZone added in v0.23.0

func (skill *Skill) IsValidForZone(zone string) bool

type Space

type Space struct {
	Id               string             `json:"space_id" db:"space_id,pk" msgpack:"space_id"`
	ParentSpaceId    string             `json:"parent_space_id" db:"parent_space_id" msgpack:"parent_space_id"`
	PoolId           string             `json:"pool_id" db:"pool_id" msgpack:"pool_id"`
	UserId           string             `json:"user_id" db:"user_id" msgpack:"user_id"`
	TemplateId       string             `json:"template_id" db:"template_id" msgpack:"template_id"`
	Shares           []string           `json:"shares" db:"shares,json" msgpack:"shares"`
	DependsOn        []string           `json:"depends_on" db:"depends_on,json" msgpack:"depends_on"`
	SharedWithUserId string             `json:"-" msgpack:"-"`
	Name             string             `json:"name" db:"name" msgpack:"name"`
	Description      string             `json:"description" db:"description" msgpack:"description"`
	Note             string             `json:"note" db:"note" msgpack:"note"`
	Stack            string             `json:"stack" db:"stack" msgpack:"stack"`
	StackPrefix      string             `json:"stack_prefix" db:"stack_prefix" msgpack:"stack_prefix"`
	Zone             string             `json:"zone" db:"zone" msgpack:"zone"`
	NodeId           string             `json:"node_id,omitempty" db:"node_id" msgpack:"node_id,omitempty"`
	Shell            string             `json:"shell" db:"shell" msgpack:"shell"`
	StartupScriptId  string             `json:"startup_script_id" db:"startup_script_id" msgpack:"startup_script_id"`
	TemplateHash     string             `json:"template_hash" db:"template_hash" msgpack:"template_hash"`
	NomadNamespace   string             `json:"nomad_namespace" db:"nomad_namespace" msgpack:"nomad_namespace"`
	ContainerId      string             `json:"container_id" db:"container_id" msgpack:"container_id"`
	IPAddress        string             `json:"ip_address,omitempty" db:"ip_address" msgpack:"ip_address,omitempty"` // KVM spaces: the VM's static IP, chosen at create time
	IconURL          string             `json:"icon_url" db:"icon_url" msgpack:"icon_url"`
	VolumeData       VolumeDataMap      `json:"volume_data" db:"volume_data" msgpack:"volume_data"`
	SSHHostSigner    string             `json:"ssh_host_signer" db:"ssh_host_signer" msgpack:"ssh_host_signer"`
	IsDeployed       bool               `json:"is_deployed" db:"is_deployed" msgpack:"is_deployed"`
	IsPending        bool               `json:"is_pending" db:"is_pending" msgpack:"is_pending"` // Flags if the space is pending a state change, starting or stopping
	IsDeleting       bool               `json:"is_deleting" db:"is_deleting" msgpack:"is_deleting"`
	IsDeleted        bool               `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
	AltNames         []AltNameEntry     `json:"alt_names" msgpack:"alt_names"`
	CustomFields     []SpaceCustomField `json:"custom_fields" db:"custom_fields,json" msgpack:"custom_fields"`
	PortForwards     []PortForwardEntry `json:"port_forwards" db:"port_forwards,json" msgpack:"port_forwards"`
	Jobs             []SpaceJob         `json:"jobs" db:"jobs,json" msgpack:"jobs"`
	JobsEnabled      bool               `json:"jobs_enabled" db:"jobs_enabled" msgpack:"jobs_enabled"`
	Restrictions     SpaceRestrictions  `json:"restrictions" db:"restrictions,json" msgpack:"restrictions"` // held until lifted from outside the space
	StartedAt        time.Time          `json:"started_at" db:"started_at" msgpack:"started_at"`
	CreatedAt        time.Time          `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedAt        hlc.Timestamp      `json:"updated_at" db:"updated_at" msgpack:"updated_at"`

	// Exclusive pool-member lease. Set on pool spaces only, while a lease
	// granted from the pool is held (or has ended but in-flight work has
	// not drained yet — the pool sweep clears all four fields once the
	// member returns to the shared pool). A nil LeaseExpiresAt means the
	// lease never expires (NULL column; the MySQL driver cannot round-trip
	// a zero time.Time).
	LeaseId         string     `json:"lease_id" db:"lease_id" msgpack:"lease_id"`
	LeaseUserId     string     `json:"lease_user_id" db:"lease_user_id" msgpack:"lease_user_id"`
	LeaseExpiresAt  *time.Time `json:"lease_expires_at" db:"lease_expires_at" msgpack:"lease_expires_at"`
	LeaseExtensions int        `json:"lease_extensions" db:"lease_extensions" msgpack:"lease_extensions"`
}

Space object

func NewSpace

func NewSpace(name string, description string, userId string, templateId string, shell string, altNames *[]AltNameEntry, zone string, iconURL string, customFields []SpaceCustomField) *Space

func (*Space) IdleTimeoutReached added in v0.36.0

func (s *Space) IdleTimeoutReached(template *Template, lastActivityAtUnix int64) bool

IdleTimeoutReached reports whether the space has gone longer than the template's idle timeout without user activity. lastActivityAtUnix is the agent-reported time of the most recent activity — terminal input, proxied connections, method calls, sustained CPU, or (on pro) filesystem writes. 0 means the agent does not report activity at all, in which case the space is never idle-stopped.

func (*Space) IsSharedWith added in v0.24.0

func (s *Space) IsSharedWith(userId string) bool

func (*Space) LeaseActive added in v0.36.0

func (s *Space) LeaseActive() bool

LeaseActive reports whether the space currently holds an unexpired exclusive lease. A nil LeaseExpiresAt means the lease never expires.

func (*Space) LeaseClear added in v0.36.0

func (s *Space) LeaseClear()

LeaseClear removes all lease fields, returning the space to the shared pool.

func (*Space) LeasePastExpiry added in v0.36.0

func (s *Space) LeasePastExpiry() bool

LeasePastExpiry reports whether the space holds a lease whose time is up (or that was released early) but which has not been reclaimed yet.

func (*Space) MaxUptimeReached

func (s *Space) MaxUptimeReached(template *Template) bool

func (*Space) NormalizeDependsOn added in v0.24.0

func (s *Space) NormalizeDependsOn()

func (*Space) NormalizeShares added in v0.24.0

func (s *Space) NormalizeShares()

func (*Space) SetSingleShare added in v0.24.0

func (s *Space) SetSingleShare(userId string)

func (*Space) SharedUserIds added in v0.24.0

func (s *Space) SharedUserIds() []string

type SpaceBucketGrant added in v0.40.0

type SpaceBucketGrant struct {
	Id       string `json:"id" msgpack:"id"`
	Name     string `json:"name" msgpack:"name"`
	ReadOnly bool   `json:"read_only" msgpack:"read_only"`
}

SpaceBucketGrant is one bucket a restricted space may still reach. The id keeps the grant on the bucket through renames and transfers; the name is the bucket's full name when the grant was made, kept for reporting.

type SpaceCustomField

type SpaceCustomField struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

func ApplyCustomFieldDefaults added in v0.34.0

func ApplyCustomFieldDefaults(template *Template, provided []SpaceCustomField) []SpaceCustomField

ApplyCustomFieldDefaults returns provided with the template's default value filled in for every custom field the create request did not mention. A field present in provided keeps its value verbatim, including an empty one, and fields without a default stay absent — both exactly as before defaults existed.

type SpaceJob added in v0.33.0

type SpaceJob struct {
	Name     string `json:"name" msgpack:"name"`
	Command  string `json:"command" msgpack:"command"`
	Schedule string `json:"schedule,omitempty" msgpack:"schedule,omitempty"` // 5-field cron expression, empty = manual only
	Enabled  bool   `json:"enabled" msgpack:"enabled"`                       // gates automatic firing only, manual runs always work
}

SpaceJob is one job definition stored on the space and pushed to the agent, which holds it in memory only — the space record is the source of truth.

type SpaceRestrictions added in v0.40.0

type SpaceRestrictions struct {
	Active    bool   `json:"active" msgpack:"active"`
	NoSecrets bool   `json:"no_secrets" msgpack:"no_secrets"`
	Files     string `json:"files" msgpack:"files"`
	// Locked locks the space's processes out of everything but file storage
	// and personal secrets, which their own restrictions govern: the knot
	// command and scripts in the space may otherwise only restart or shut it
	// down and show its restrictions. Requests from outside the space, which
	// the agent carries out, such as port forwards and scripts run from the
	// desktop, still work.
	Locked bool `json:"locked" msgpack:"locked"`
	// LimitBuckets makes Buckets an allowlist: buckets not in it are hidden.
	LimitBuckets bool               `json:"limit_buckets" msgpack:"limit_buckets"`
	Buckets      []SpaceBucketGrant `json:"buckets" msgpack:"buckets"`
}

SpaceRestrictions narrow what a space's own credential (its agent token) may do, on top of what its template allows. They are applied from inside the space or by its owner, can only ever be tightened from inside the space, and hold across restarts until lifted from outside the space, or until a pool member goes back to its pool.

Any restriction confines the space: its credential may then act only on the space itself, the buckets it is allowed, tunnels and port forwards, and may start or stop other spaces — everything else, such as making API tokens or running commands in other spaces, is refused, so the restrictions can't be stepped around.

func (*SpaceRestrictions) BucketAccess added in v0.40.0

func (r *SpaceRestrictions) BucketAccess(bucketId string) (allowed, readOnly bool)

BucketAccess reports whether a restricted space may reach a bucket and, if so, whether only to read it. An inactive restriction allows everything.

func (SpaceRestrictions) Narrow added in v0.40.0

Narrow returns the restrictions with more applied on top. The result is never less strict than r in any way: secrets stay blocked once blocked, the file mode only gets stricter, and a bucket allowlist only shrinks — a bucket missing from either side is dropped, and one read-only on either side stays read-only.

type SpaceUsageSample added in v0.24.0

type SpaceUsageSample struct {
	Id                    string        `json:"space_usage_id" db:"space_usage_id,pk" msgpack:"space_usage_id"`
	SpaceId               string        `json:"space_id" db:"space_id" msgpack:"space_id"`
	UserId                string        `json:"user_id" db:"user_id" msgpack:"user_id"`
	BucketKind            string        `json:"bucket_kind" db:"bucket_kind" msgpack:"bucket_kind"`
	BucketStart           time.Time     `json:"bucket_start" db:"bucket_start" msgpack:"bucket_start"`
	CPUPercent            float64       `json:"cpu_percent" db:"cpu_percent" msgpack:"cpu_percent"`
	MemoryUsedBytes       uint64        `json:"memory_used_bytes" db:"memory_used_bytes" msgpack:"memory_used_bytes"`
	MemoryLimitBytes      uint64        `json:"memory_limit_bytes" db:"memory_limit_bytes" msgpack:"memory_limit_bytes"`
	DiskUsedBytes         uint64        `json:"disk_used_bytes" db:"disk_used_bytes" msgpack:"disk_used_bytes"`
	DiskLimitBytes        uint64        `json:"disk_limit_bytes" db:"disk_limit_bytes" msgpack:"disk_limit_bytes"`
	ActivityWriteCount    uint32        `json:"activity_write_count" db:"activity_write_count" msgpack:"activity_write_count"`
	ActivityCreateCount   uint32        `json:"activity_create_count" db:"activity_create_count" msgpack:"activity_create_count"`
	ActivityDeleteCount   uint32        `json:"activity_delete_count" db:"activity_delete_count" msgpack:"activity_delete_count"`
	ActivityRenameCount   uint32        `json:"activity_rename_count" db:"activity_rename_count" msgpack:"activity_rename_count"`
	ActivityDistinctPaths uint32        `json:"activity_distinct_paths" db:"activity_distinct_paths" msgpack:"activity_distinct_paths"`
	ActivitySpaceStarts   uint32        `json:"activity_space_starts" db:"activity_space_starts" msgpack:"activity_space_starts"`
	ActivitySpaceStops    uint32        `json:"activity_space_stops" db:"activity_space_stops" msgpack:"activity_space_stops"`
	ActivitySpaceCreates  uint32        `json:"activity_space_creates" db:"activity_space_creates" msgpack:"activity_space_creates"`
	ActivitySpaceDeletes  uint32        `json:"activity_space_deletes" db:"activity_space_deletes" msgpack:"activity_space_deletes"`
	LastActivityAt        *time.Time    `json:"last_activity_at,omitempty" db:"last_activity_at" msgpack:"last_activity_at,omitempty"`
	CreatedAt             time.Time     `json:"created_at" db:"created_at" msgpack:"created_at"`
	UpdatedAt             hlc.Timestamp `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
}

func NewSpaceUsageSample added in v0.24.0

func NewSpaceUsageSample(spaceId, userId, bucketKind string, bucketStart time.Time) *SpaceUsageSample

type SpaceVolume

type SpaceVolume struct {
	Id        string `json:"id"`
	Namespace string `json:"Namespace"`
	Type      string `json:"type,omitempty"`
}

func (*SpaceVolume) Scan

func (sv *SpaceVolume) Scan(value interface{}) error

Scan implements the sql.Scanner interface.

func (SpaceVolume) Value

func (sv SpaceVolume) Value() (driver.Value, error)

Value implements the driver.Valuer interface.

type StackComponent added in v0.24.0

type StackComponent struct {
	Name            string             `json:"name" db:"name"`
	TemplateId      string             `json:"template_id" db:"template_id"`
	Description     string             `json:"description" db:"description"`
	Shell           string             `json:"shell" db:"shell"`
	StartupScriptId string             `json:"startup_script_id" db:"startup_script_id"`
	DependsOn       []string           `json:"depends_on" db:"depends_on,json"`
	CustomFields    []StackCustomField `json:"custom_fields" db:"custom_fields,json"`
	PortForwards    []StackPortForward `json:"port_forwards" db:"port_forwards,json"`
}

type StackCustomField added in v0.24.0

type StackCustomField struct {
	Name  string `json:"name" db:"name"`
	Value string `json:"value" db:"value"`
}

type StackDefinition added in v0.24.0

type StackDefinition struct {
	Id            string           `json:"stack_definition_id" db:"stack_definition_id,pk"`
	UserId        string           `json:"user_id" db:"user_id"`
	Name          string           `json:"name" db:"name"`
	Description   string           `json:"description" db:"description"`
	IconURL       string           `json:"icon_url" db:"icon_url"`
	Groups        []string         `json:"groups" db:"groups,json"`
	Zones         []string         `json:"zones" db:"zones,json"`
	Active        bool             `json:"active" db:"active"`
	IsDeleted     bool             `json:"is_deleted" db:"is_deleted"`
	IsManaged     bool             `json:"is_managed" db:"is_managed"`
	Components    []StackComponent `json:"components" db:"components,json"`
	CreatedUserId string           `json:"created_user_id" db:"created_user_id"`
	CreatedAt     time.Time        `json:"created_at" db:"created_at"`
	UpdatedUserId string           `json:"updated_user_id" db:"updated_user_id"`
	UpdatedAt     hlc.Timestamp    `json:"updated_at" db:"updated_at"`
}

func NewStackDefinition added in v0.24.0

func NewStackDefinition(
	name string,
	description string,
	iconUrl string,
	groups []string,
	zones []string,
	active bool,
	components []StackComponent,
	ownerUserId string,
	createdUserId string,
) *StackDefinition

func (*StackDefinition) IsGlobal added in v0.24.0

func (sd *StackDefinition) IsGlobal() bool

IsGlobal returns true if the definition is a system/global definition (UserId is empty)

func (*StackDefinition) IsValidForZone added in v0.24.0

func (sd *StackDefinition) IsValidForZone(zone string) bool

IsValidForZone determines whether the stack definition is valid for the specified zone. Follows the same !-prefix negation logic as Script.IsValidForZone.

type StackPortForward added in v0.24.0

type StackPortForward struct {
	ToSpace    string `json:"to_space" db:"to_space"`
	LocalPort  int    `json:"local_port" db:"local_port"`
	RemotePort int    `json:"remote_port" db:"remote_port"`
}

type Template

type Template struct {
	Id               string   `json:"template_id" db:"template_id,pk"`
	Name             string   `json:"name" db:"name"`
	Description      string   `json:"description" db:"description"`
	Hash             string   `json:"hash" db:"hash"`
	Platform         string   `json:"platform" db:"platform"`
	IconURL          string   `json:"icon_url" db:"icon_url"`
	Job              string   `json:"job" db:"job"`
	Volumes          string   `json:"volumes" db:"volumes"`
	Groups           []string `json:"groups" db:"groups,json"`
	Active           bool     `json:"active" db:"active"`
	WithTerminal     bool     `json:"with_terminal" db:"with_terminal"`
	WithVSCodeTunnel bool     `json:"with_vscode_tunnel" db:"with_vscode_tunnel"`
	WithCodeServer   bool     `json:"with_code_server" db:"with_code_server"`
	WithSSH          bool     `json:"with_ssh" db:"with_ssh"`
	WithRunCommand   bool     `json:"with_run_command" db:"with_run_command"`
	// WithVNC exposes the VM's built-in QEMU VNC display (the framebuffer
	// QEMU itself renders — bootloader, console, desktop) in the browser via
	// knot's websocket bridge. KVM-only; nothing is installed in the guest.
	WithVNC                  bool                   `json:"with_vnc" db:"with_vnc"`
	AllowNodeMigration       bool                   `json:"allow_node_migration" db:"allow_node_migration"`
	StartupScriptId          string                 `json:"startup_script_id" db:"startup_script_id"`
	ShutdownScriptId         string                 `json:"shutdown_script_id" db:"shutdown_script_id"`
	ComputeUnits             uint32                 `json:"compute_units" db:"compute_units"`
	StorageUnits             uint32                 `json:"storage_units" db:"storage_units"`
	ScheduleEnabled          bool                   `json:"schedule_enabled" db:"schedule_enabled"`
	AutoStart                bool                   `json:"auto_start" db:"auto_start"`
	IsDeleted                bool                   `json:"is_deleted" db:"is_deleted"`
	IsManaged                bool                   `json:"is_managed" db:"is_managed"`
	Schedule                 []TemplateScheduleDays `json:"schedule" db:"schedule,json"`
	Zones                    []string               `json:"zones" db:"zones,json"`
	CustomFields             []TemplateCustomField  `json:"custom_fields" db:"custom_fields,json"`
	MaxUptime                uint32                 `json:"max_uptime" db:"max_uptime"`
	MaxUptimeUnit            string                 `json:"max_uptime_unit" db:"max_uptime_unit"`
	IdleTimeout              uint32                 `json:"idle_timeout" db:"idle_timeout"`
	IdleTimeoutUnit          string                 `json:"idle_timeout_unit" db:"idle_timeout_unit"`
	HealthCheckType          string                 `json:"health_check_type" db:"health_check_type"`
	HealthCheckConfig        string                 `json:"health_check_config" db:"health_check_config"`
	HealthCheckSkipSSLVerify bool                   `json:"health_check_skip_ssl_verify" db:"health_check_skip_ssl_verify"`
	HealthCheckTimeout       uint32                 `json:"health_check_timeout" db:"health_check_timeout"`
	HealthCheckInterval      uint32                 `json:"health_check_interval" db:"health_check_interval"`
	HealthCheckMaxFailures   uint32                 `json:"health_check_max_failures" db:"health_check_max_failures"`
	HealthCheckAutoRestart   bool                   `json:"health_check_auto_restart" db:"health_check_auto_restart"`
	DisableUserActivity      bool                   `json:"disable_user_activity" db:"disable_user_activity"`
	DisableFileStorage       bool                   `json:"disable_file_storage" db:"disable_file_storage"`
	DisableUserSecrets       bool                   `json:"disable_user_secrets" db:"disable_user_secrets"`
	Ports                    []TemplatePort         `json:"ports" db:"ports,json"`
	// Port forwards seeded into every space created from this template, so
	// client spaces connect to their services automatically when they start
	// (the same restore-on-start replay as manually persisted forwards).
	// Entries use target references — bare name, user--name — resolved and
	// authorized per connection. Pro ships the template editor for this;
	// the API accepts it everywhere.
	PortForwards []PortForwardEntry `json:"port_forwards" db:"port_forwards,json"`
	Jobs         []SpaceJob         `json:"jobs" db:"jobs,json"`
	// KVM network configuration, derived from the job spec's network:
	// block. Bridged mode attaches VMs to a host bridge (or libvirt
	// network) and gives each space a static IP chosen from the
	// kvm_ip_range at create time; NAT mode attaches to a libvirt NAT
	// network (named by the bridge field, default "default") and the VM
	// DHCPs — no addresses to manage.
	KvmNetworkMode  string        `json:"kvm_network_mode,omitempty" db:"kvm_network_mode"`
	KvmNetworkCidr  string        `json:"kvm_network_cidr,omitempty" db:"kvm_network_cidr"`
	KvmIPRangeStart string        `json:"kvm_ip_range_start,omitempty" db:"kvm_ip_range_start"`
	KvmIPRangeEnd   string        `json:"kvm_ip_range_end,omitempty" db:"kvm_ip_range_end"`
	KvmGateway      string        `json:"kvm_gateway,omitempty" db:"kvm_gateway"`
	KvmBridge       string        `json:"kvm_bridge,omitempty" db:"kvm_bridge"`
	CreatedUserId   string        `json:"created_user_id" db:"created_user_id"`
	CreatedAt       time.Time     `json:"created_at" db:"created_at"`
	UpdatedUserId   string        `json:"updated_user_id" db:"updated_user_id"`
	UpdatedAt       hlc.Timestamp `json:"updated_at" db:"updated_at"`
}

Template object

func NewTemplate

func NewTemplate(
	name string,
	description string,
	job string,
	volumes string,
	userId string,
	groups []string,
	platform string,
	withTerminal bool,
	withVSCodeTunnel bool,
	withCodeServer bool,
	withSSH bool,
	withRunCommand bool,
	allowNodeMigration bool,
	startupScriptId string,
	shutdownScriptId string,
	computeUnits uint32,
	storageUnits uint32,
	scheduleEnabled bool,
	schedule *[]TemplateScheduleDays,
	zones []string,
	autoStart bool,
	active bool,
	maxUptime uint32,
	maxUptimeUnit string,
	iconURL string,
	customFields []TemplateCustomField,
) *Template

func (*Template) AllowedBySchedule

func (template *Template) AllowedBySchedule() bool

func (*Template) GetVolumes

func (template *Template) GetVolumes(space *Space, user *User, variables map[string]interface{}) (*CSIVolumes, error)

func (*Template) IdleTimeoutDuration added in v0.36.0

func (template *Template) IdleTimeoutDuration() time.Duration

IdleTimeoutDuration returns the template's idle timeout — how long a deployed space may go without user activity before the server stops it — or 0 when idle shutdown is disabled. Unlike MaxUptime a value of 0 with a unit set also means disabled: an accidentally blank value must never stop a space the moment it starts.

func (*Template) IsKvm added in v0.35.0

func (template *Template) IsKvm() bool

func (*Template) IsKvmBridged added in v0.35.0

func (template *Template) IsKvmBridged() bool

IsKvmBridged reports whether KVM spaces of this template carry a static IP from the template's network range.

func (*Template) IsKvmNat added in v0.35.0

func (template *Template) IsKvmNat() bool

IsKvmNat reports whether KVM spaces of this template attach to a libvirt NAT network and DHCP instead of carrying a static IP.

func (*Template) IsLocalContainer

func (template *Template) IsLocalContainer() bool

func (*Template) IsManual

func (template *Template) IsManual() bool

func (*Template) IsNodeRuntime added in v0.35.0

func (template *Template) IsNodeRuntime() bool

IsNodeRuntime reports whether spaces of this template run directly on a cluster node (local container runtimes and KVM virtual machines) rather than through an external scheduler. Node-runtime spaces are pinned to a node at create time and their requests are forwarded to the owning node.

func (*Template) IsPortShared added in v0.36.0

func (t *Template) IsPortShared(port uint16) bool

IsPortShared reports whether the template declares the given port shared: reachable by every user of the server through port forwards, not just the space's owner. Only shared-protocol ports are cross-user forward targets; every other port is owner-only, same as an undeclared one.

func (*Template) IsValidForZone added in v0.19.0

func (template *Template) IsValidForZone(zone string) bool

IsValidForZone determines whether the template is valid for deployment in the specified zone. The function evaluates zone restrictions based on the template's Zones configuration. If no zones are specified, the template is considered valid for all zones. Zone names prefixed with '!' are treated as exclusions (negated zones). The function first checks for exclusions, then checks for explicit inclusions.

zone is the target zone name to validate against the template's zone restrictions.

Returns true if the template can be deployed in the specified zone, false otherwise.

func (*Template) UpdateHash

func (template *Template) UpdateHash()

type TemplateCustomField

type TemplateCustomField struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	// Type controls how the space form renders the field: text (default)
	// or autocomplete. Autocomplete requires Handler - a plugin field
	// handler id (plugin.<name>.<id>) that serves the suggestions.
	Type    string `json:"type,omitempty"`
	Handler string `json:"handler,omitempty"`
	// Language selects the ace mode/completions for textarea fields:
	// yaml, toml, json, markdown, shell or scriptling ("" is plain text).
	Language string `json:"language,omitempty"`
	// Default is the value a space starts with for this field. It is
	// presence-based: applied only when the create request omits the
	// field entirely, never when the field arrives with an empty value —
	// clearing a prefilled default is an intentional blank.
	Default string `json:"default,omitempty"`
	// Required marks a field the space form refuses to leave blank (and
	// the space create/update API rejects): absent, empty or
	// whitespace-only values fail. A bool field is never blank.
	Required bool `json:"required,omitempty"`
	// Options is a select field's manual option list — the alternative to
	// Handler. Values are stored verbatim.
	Options []string `json:"options,omitempty"`
	// ShowOnCreate shows an optional field on the create-space form with the
	// required ones, instead of behind its "optional fields" toggle. It only
	// changes how the form is laid out, so it is left out of the template
	// hash. Absent (older templates) means false.
	ShowOnCreate bool `json:"show_on_create,omitempty"`
}

type TemplatePort added in v0.25.0

type TemplatePort struct {
	Name     string `json:"name"`
	Port     uint16 `json:"port"`
	Protocol string `json:"protocol"`
}

type TemplateScheduleDays

type TemplateScheduleDays struct {
	Enabled bool   `json:"enabled"`
	From    string `json:"from"`
	To      string `json:"to"`
}

type TemplateVar

type TemplateVar struct {
	Id            string        `json:"templatevar_id" db:"templatevar_id,pk"`
	Name          string        `json:"name" db:"name"`
	Zones         []string      `json:"zones" db:"zones,json"`
	Value         string        `json:"value" db:"value"`
	Protected     bool          `json:"protected" db:"protected"`
	Local         bool          `json:"local" db:"local"`
	Restricted    bool          `json:"restricted" db:"restricted"`
	IsDeleted     bool          `json:"is_deleted" db:"is_deleted"`
	IsManaged     bool          `json:"is_managed" db:"is_managed"`
	CreatedUserId string        `json:"created_user_id" db:"created_user_id"`
	CreatedAt     time.Time     `json:"created_at" db:"created_at"`
	UpdatedUserId string        `json:"updated_user_id" db:"updated_user_id"`
	UpdatedAt     hlc.Timestamp `json:"updated_at" db:"updated_at"`
}

Template Variable object

func NewTemplateVar

func NewTemplateVar(name string, zones []string, local bool, value string, protected bool, restricted bool, userId string) *TemplateVar

func (*TemplateVar) DecryptSetValue

func (templateVar *TemplateVar) DecryptSetValue(text string)

func (*TemplateVar) GetValueEncrypted

func (templateVar *TemplateVar) GetValueEncrypted() string

type Token

type Token struct {
	Id           string        `json:"token_id" db:"token_id,pk"`
	UserId       string        `json:"user_id" db:"user_id"`
	Name         string        `json:"name" db:"name"`
	ExpiresAfter time.Time     `json:"expires_after" db:"expires_after"`
	UpdatedAt    hlc.Timestamp `json:"updated_at" db:"updated_at"`
	IsDeleted    bool          `json:"is_deleted" db:"is_deleted"`
	// Scopes restricts which endpoint groups this token can reach.
	// nil/empty = unrestricted (backward compatible with pre-scopes tokens).
	// Non-empty = token may only reach endpoints covered by the listed scopes.
	Scopes []string `json:"scopes,omitempty" db:"scopes,json"`
	// RefreshToken marks tokens issued via the OAuth2 authorization-code
	// flow; only these may be extended through the /token refresh grant.
	RefreshToken bool `json:"refresh_token,omitempty" db:"refresh_token"`
}

Session object

func NewToken

func NewToken(name string, userId string) *Token

type Usage

type Usage struct {
	ComputeUnits               uint32
	StorageUnits               uint32
	NumberSpaces               int
	NumberSpacesDeployed       int
	NumberSpacesDeployedInZone int
}

type User

type User struct {
	Id                    string                      `json:"user_id" db:"user_id,pk" msgpack:"user_id"`
	Username              string                      `json:"username" db:"username" msgpack:"username"`
	Email                 string                      `json:"email" db:"email" msgpack:"email"`
	Password              string                      `json:"password" db:"password" msgpack:"password"`
	TOTPSecret            string                      `json:"totp_secret" db:"totp_secret" msgpack:"totp_secret"`
	ServicePassword       string                      `json:"service_password" db:"service_password" msgpack:"service_password"`
	SSHPublicKey          string                      `json:"ssh_public_key" db:"ssh_public_key" msgpack:"ssh_public_key"`
	SSHPrivateKey         string                      `json:"ssh_private_key" db:"ssh_private_key" msgpack:"ssh_private_key"`
	OnePasswordToken      string                      `json:"onepassword_token" db:"onepassword_token" msgpack:"onepassword_token"` // encrypted 1Password service account token (Knot Pro user secrets)
	GitHubUsername        string                      `json:"github_username" db:"github_username" msgpack:"github_username"`
	ExternalAuthProviders map[string]ExternalProvider `json:"external_auth_providers" db:"external_auth_providers,json" msgpack:"external_auth_providers"`
	Roles                 []string                    `json:"roles" db:"roles,json" msgpack:"roles"`
	Groups                []string                    `json:"groups" db:"groups,json" msgpack:"groups"`
	// LinkedUsers holds the accounts this user may become — fast user
	// switching, one way. The link grants nothing in return: a listed
	// user cannot become this one. Maintained only through the
	// link/unlink endpoints.
	LinkedUsers    []string       `json:"linked_users" db:"linked_users,json" msgpack:"linked_users"`
	Active         bool           `json:"active" db:"active" msgpack:"active"`
	IsDeleted      bool           `json:"is_deleted" db:"is_deleted" msgpack:"is_deleted"`
	MaxSpaces      uint32         `json:"max_spaces" db:"max_spaces" msgpack:"max_spaces"`
	ComputeUnits   uint32         `json:"compute_units" db:"compute_units" msgpack:"compute_units"`
	StorageUnits   uint32         `json:"storage_units" db:"storage_units" msgpack:"storage_units"`
	MaxTunnels     uint32         `json:"max_tunnels" db:"max_tunnels" msgpack:"max_tunnels"`
	FileStorageMB  uint32         `json:"file_storage_mb" db:"file_storage_mb" msgpack:"file_storage_mb"`
	MaxBuckets     uint32         `json:"max_buckets" db:"max_buckets" msgpack:"max_buckets"`
	PreferredShell string         `json:"preferred_shell" db:"preferred_shell" msgpack:"preferred_shell"`
	Timezone       string         `json:"timezone" db:"timezone" msgpack:"timezone"`
	Preferences    map[string]any `json:"preferences" db:"preferences,json" msgpack:"preferences"`
	LastLoginAt    *time.Time     `json:"last_login_at" db:"last_login_at" msgpack:"last_login_at"`
	UpdatedAt      hlc.Timestamp  `json:"updated_at" db:"updated_at" msgpack:"updated_at"`
	CreatedAt      time.Time      `json:"created_at" db:"created_at" msgpack:"created_at"`
}

User object

func NewUser

func NewUser(username string, email string, password string, roles []string, groups []string, sshPublicKey string, preferredShell string, timezone string, maxSpaces uint32, githubUsername string, computeUnits uint32, storageUnits uint32, maxTunnels uint32) *User

func (*User) CheckPassword

func (u *User) CheckPassword(password string) bool

Check the password for the user

func (*User) ClearOAuthTokens added in v0.24.0

func (u *User) ClearOAuthTokens(providerID string)

func (*User) GetNavStarred added in v0.32.0

func (u *User) GetNavStarred() []string

GetNavStarred returns the user's pinned (starred) navigation URLs in their chosen display order, or nil if none are set. JSON round-trips decode the stored array as []any, so coerce back to []string here.

func (*User) GetOAuthRefreshToken added in v0.24.0

func (u *User) GetOAuthRefreshToken(providerID, encryptionKey string) string

GetOAuthRefreshToken returns the decrypted OAuth refresh token for the given provider, or empty string.

func (*User) GetOAuthToken added in v0.23.7

func (u *User) GetOAuthToken(providerID, encryptionKey string) string

GetOAuthToken returns the decrypted OAuth access token for the given provider, or empty string.

func (*User) GetSSHPrivateKeyDecrypted added in v0.25.0

func (u *User) GetSSHPrivateKeyDecrypted(encryptionKey string) string

func (*User) GrantedPermissionKeys added in v0.34.0

func (u *User) GrantedPermissionKeys() []string

GrantedPermissionKeys returns the stable snake_case keys of the built-in permissions the user holds across their roles; the fixed admin role holds all of them. Keys — not display names — are the machine surface (user.has_permission), so rewording a permission's display string can never break plugin logic. The enforcement surface remains HasPermission.

func (*User) GrantedPluginPermissions added in v0.34.0

func (u *User) GrantedPluginPermissions() []string

GrantedPluginPermissions returns the qualified plugin grants (e.g. "plugin.metrics.read") the user holds across their roles. The admin role passes every plugin permission check without carrying grants; callers treat is-admin as the superset signal.

func (*User) HasAnyGroup

func (u *User) HasAnyGroup(groups *[]string) bool

func (*User) HasPermission

func (u *User) HasPermission(permission uint16) bool

func (*User) HasPluginPermission added in v0.34.0

func (u *User) HasPluginPermission(name string) bool

func (*User) IsAdmin

func (u *User) IsAdmin() bool

func (*User) PassesPluginGate added in v0.34.0

func (u *User) PassesPluginGate(permission string) bool

HasPluginPermission reports whether any of the user's roles carries the fully qualified plugin grant (e.g. "plugin.metrics.read"). Plugin grants are text so they are cluster-order independent and survive plugin uninstall/reinstall inertly (PLUGINS2.md §5). The fixed admin role cannot be granted per-plugin permissions through the API, so it passes every plugin permission check. PassesPluginGate reports whether the user passes a declared plugin permission gate: an empty permission means any logged-in user, a set one requires the qualified grant (admins pass every check). This is the one predicate every declared gate — pages, handlers, menus, tools, field handlers — checks through.

func (*User) SetNavStarred added in v0.32.0

func (u *User) SetNavStarred(order []string)

SetNavStarred stores the given navigation URLs as the user's pinned set in the supplied order. An empty slice clears the preference (opts out of the starred layout and returns the menu to its default arrangement).

func (*User) SetOAuthTokens added in v0.24.0

func (u *User) SetOAuthTokens(providerID, token, refreshToken, encryptionKey string)

SetOAuthTokens stores encrypted OAuth tokens for the given provider. Refresh tokens are preserved when the provider omits them on a later login.

func (*User) SetPassword

func (u *User) SetPassword(password string) error

Set the password for the user

func (*User) SetSSHPrivateKeyEncrypted added in v0.25.0

func (u *User) SetSSHPrivateKeyEncrypted(privateKey string, encryptionKey string)

ClearOAuthTokens removes the stored tokens for the given provider.

type Volume

type Volume struct {
	Id            string        `json:"volume_id" db:"volume_id,pk"`
	Name          string        `json:"name" db:"name"`
	Zone          string        `json:"zone" db:"zone"`
	NodeId        string        `json:"node_id" db:"node_id"`
	Platform      string        `json:"platform" db:"platform"`
	Definition    string        `json:"definition" db:"definition"`
	Active        bool          `json:"active" db:"active"`
	IsDeleted     bool          `json:"is_deleted" db:"is_deleted"`
	CreatedUserId string        `json:"created_user_id" db:"created_user_id"`
	CreatedAt     time.Time     `json:"created_at" db:"created_at"`
	UpdatedUserId string        `json:"updated_user_id" db:"updated_user_id"`
	UpdatedAt     hlc.Timestamp `json:"updated_at" db:"updated_at"`
}

Template object

func NewVolume

func NewVolume(name string, definition string, userId string, platform string) *Volume

func (*Volume) GetVolume

func (volume *Volume) GetVolume(variables map[string]interface{}) (*CSIVolumes, error)

type VolumeDataMap

type VolumeDataMap map[string]SpaceVolume

VolumeDataMap is a custom type that implements the sql.Scanner and driver.Valuer interfaces

func (*VolumeDataMap) Scan

func (v *VolumeDataMap) Scan(value interface{}) error

Scan implements the sql.Scanner interface.

func (VolumeDataMap) Value

func (v VolumeDataMap) Value() (driver.Value, error)

Value implements the driver.Valuer interface.

type WebhookConfig added in v0.28.0

type WebhookConfig struct {
	URL           string            `json:"url" msgpack:"url"`
	Secret        string            `json:"secret" msgpack:"secret"`
	Headers       map[string]string `json:"headers,omitempty" msgpack:"headers,omitempty"`
	BodyTemplate  string            `json:"body_template" msgpack:"body_template"`
	SkipTLSVerify bool              `json:"skip_tls_verify" msgpack:"skip_tls_verify"`
}

Jump to

Keyboard shortcuts

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