plugin

package
v0.10.0 Latest Latest
Warning

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

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

Documentation

Overview

Package plugin defines the unified interface for GoatKit plugins.

Plugins can be implemented as either:

  • WASM modules (portable, sandboxed, via wazero)
  • gRPC services (native, for I/O-heavy workloads, via go-plugin)

The host doesn't care which runtime backs a plugin - both implement this interface and are managed uniformly by the plugin manager.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArticleAttachment added in v0.10.0

type ArticleAttachment struct {
	ID          int64  `json:"id"`
	ArticleID   int64  `json:"article_id"`
	Filename    string `json:"filename"`
	ContentType string `json:"content_type"`
	Size        int64  `json:"size"`
	URL         string `json:"url"`
}

ArticleAttachment describes a file attached to an article. ID addresses the attachment within its article (always pair it with ArticleID): the OTRS ArticleStorageFS backend numbers attachments per article. URL is the same-origin download path built by the host; append "/view" for the inline viewer or "/thumbnail" for a preview image. Plugins must not build it.

type CascadeSpec added in v0.8.0

type CascadeSpec struct {
	EntityType   string `json:"entity_type"`              // ticket, contact, agent, organisation, etc.
	OnSoftDelete string `json:"on_soft_delete,omitempty"` // plugin function for soft delete
	OnHardDelete string `json:"on_hard_delete,omitempty"` // plugin function for hard delete
}

CascadeSpec declares a plugin's cascade handler for entity deletion.

type CustomFieldFilter added in v0.8.0

type CustomFieldFilter struct {
	Field    string `json:"field"`            // field name (plugin prefix stripped)
	Operator string `json:"operator"`         // eq, neq, gt, lt, gte, lte, like, in, between, near
	Value    any    `json:"value"`            // comparison value
	Value2   any    `json:"value2,omitempty"` // second value for between (upper bound) and near (radius km)
}

CustomFieldFilter is a query filter used by CustomFieldsQuery.

type CustomFieldSpec added in v0.8.0

type CustomFieldSpec struct {
	Name        string          `json:"name"`              // machine name (auto-prefixed with plugin name)
	Label       string          `json:"label"`             // display label (can be i18n key)
	EntityType  string          `json:"entity_type"`       // "contact", "agent", "organisation", etc.
	FieldType   string          `json:"field_type"`        // "text", "select", "point", etc.
	Section     string          `json:"section,omitempty"` // UI section grouping (default: "custom")
	Order       int             `json:"order,omitempty"`   // sort within section
	Required    bool            `json:"required,omitempty"`
	Description string          `json:"description,omitempty"` // help text below input
	Placeholder string          `json:"placeholder,omitempty"`
	Config      json.RawMessage `json:"config,omitempty"` // type-specific config (options, regex, etc.)
}

CustomFieldSpec declares a custom field a plugin needs on a GoatKit entity. The platform creates, stores, validates, indexes, and renders these fields.

type ErrorCodeSpec

type ErrorCodeSpec struct {
	Code       string `json:"code"`        // error code without prefix, e.g. "export_failed"
	Message    string `json:"message"`     // default English message
	HTTPStatus int    `json:"http_status"` // suggested HTTP status code
}

ErrorCodeSpec defines an API error code provided by the plugin. The plugin name is automatically prefixed to the code by the host (e.g., code "export_failed" in plugin "stats" becomes "stats:export_failed").

type FieldOp added in v0.8.1

type FieldOp struct {
	Op      string   `json:"op"`                // Operation name.
	Value   any      `json:"value,omitempty"`   // Operand value.
	Expect  any      `json:"expect,omitempty"`  // Expected current value (cas only).
	Floor   *float64 `json:"floor,omitempty"`   // Minimum bound after increment.
	Ceiling *float64 `json:"ceiling,omitempty"` // Maximum bound after increment.
}

FieldOp represents an atomic operation on a custom field value. Pass a FieldOp as a value in CustomFieldsSet to perform an atomic update instead of the default overwrite behaviour.

Supported operations:

  • "increment": Atomically add Value to a numeric field (integer/decimal). Optional Floor/Ceiling enforce bounds; the update is rejected if breached.
  • "append": Add Value (string) to a multi_select field without overwriting.
  • "remove": Remove Value (string) from a multi_select field.
  • "cas": Compare-and-swap — set to Value only if current value equals Expect.
  • "toggle": Flip a boolean field (no Value needed).

type FileInfo added in v0.8.1

type FileInfo struct {
	Key         string            `json:"key"`
	Size        int64             `json:"size"`
	ContentType string            `json:"content_type,omitempty"`
	Metadata    map[string]string `json:"metadata,omitempty"`
	ModifiedAt  string            `json:"modified_at,omitempty"`
}

FileInfo describes a stored file.

type GKRegistration

type GKRegistration struct {
	// Identity
	Name        string `json:"name"`           // unique identifier, e.g. "stats"
	Version     string `json:"version"`        // semver, e.g. "1.0.0"
	Description string `json:"description"`    // human-readable description
	Author      string `json:"author"`         // author or organization
	License     string `json:"license"`        // SPDX identifier, e.g. "Apache-2.0"
	Homepage    string `json:"homepage"`       // URL to plugin docs/repo
	Icon        string `json:"icon,omitempty"` // SVG icon content, FontAwesome class (e.g. "fa-book"), or bundled icon path

	// Capabilities - what the plugin exposes to the host
	Routes     []RouteSpec     `json:"routes,omitempty"`      // HTTP routes to register
	MenuItems  []MenuItemSpec  `json:"menu_items,omitempty"`  // navigation menu entries
	Widgets    []WidgetSpec    `json:"widgets,omitempty"`     // dashboard widgets
	Jobs       []JobSpec       `json:"jobs,omitempty"`        // scheduled/cron tasks
	Templates  []TemplateSpec  `json:"templates,omitempty"`   // template overrides/additions
	I18n       *I18nSpec       `json:"i18n,omitempty"`        // translations provided by plugin
	ErrorCodes []ErrorCodeSpec `json:"error_codes,omitempty"` // API error codes provided by plugin

	// EventAuthorizer names the plugin function the host calls before a
	// browser subscribes to GET /api/v1/plugins/{name}/events/{channel}.
	// The function receives {"channel": "<channel>"} plus the caller envelope
	// (_user_id, _user_role, _is_admin, ...) and returns {"allow": true} to
	// permit the subscription; anything else is refused with 403. Unset: any
	// authenticated agent may subscribe to every channel of the plugin.
	EventAuthorizer string `json:"event_authorizer,omitempty"`

	// Navigation control
	HideMenuItems []string `json:"hide_menu_items,omitempty"` // IDs of default menu items to hide (dashboard, tickets, queues, phone_ticket, email_ticket, admin)
	LandingPage   string   `json:"landing_page,omitempty"`    // URL path to redirect to after login (e.g. "/myplugin")

	// Access control — groups the plugin needs, auto-created on load
	Groups []GroupSpec `json:"groups,omitempty"` // groups for RBAC (use "group:<name>" in route middleware)

	// Custom fields the plugin needs on GoatKit entities.
	// Field names are auto-prefixed with the plugin name to prevent collisions.
	CustomFields []CustomFieldSpec `json:"custom_fields,omitempty"`

	// UIs the plugin provides. Each UI is an independent application
	// with its own routes, branding, navigation, and auth.
	UIs []UISpec `json:"uis,omitempty"`

	// Cascade handlers for entity deletion.
	// Called when platform entities are soft/hard deleted.
	Cascades []CascadeSpec `json:"cascades,omitempty"`

	// MCP (Model Context Protocol) tools.
	// Plugins can optionally declare MCP tools with full input schemas.
	// When declared, these override auto-generated tools from routes.
	// Tool names are auto-prefixed with the plugin name.
	MCPTools []MCPToolSpec `json:"mcp_tools,omitempty"`

	// Setup tasks the plugin contributes to the host's Setup Assistant.
	// Each task becomes a mini-wizard entry in the admin setup catalog; running
	// one dispatches to the plugin handler named in SetupTaskSpec.Handler.
	SetupTasks []SetupTaskSpec `json:"setup_tasks,omitempty"`

	// Org context
	// SkipOrgInjection disables automatic _org_id injection into plugin call
	// params. Set to true for plugins that handle multi-org queries themselves.
	SkipOrgInjection bool `json:"skip_org_injection,omitempty"`

	// Requirements
	MinHostVersion string           `json:"min_host_version,omitempty"` // minimum GoatFlow version
	Permissions    []string         `json:"permissions,omitempty"`      // required host permissions (legacy, use ResourceRequest)
	Resources      *ResourceRequest `json:"resources,omitempty"`        // requested resource limits
}

GKRegistration describes what a plugin provides to the host. This is returned by GKRegister() - the self-describing plugin protocol.

type GroupSpec

type GroupSpec struct {
	Name        string `json:"name"`        // group name, e.g. "myplugin-users"
	Description string `json:"description"` // human-readable description for admin UI
}

GroupSpec defines a group that a plugin requires for access control. Groups are auto-created in the GoatFlow groups table when the plugin loads. Routes can reference them via middleware: ["auth", "group:myplugin-users"].

type HostAPI

type HostAPI interface {
	// Database
	DBQuery(ctx context.Context, query string, args ...any) ([]map[string]any, error)
	DBExec(ctx context.Context, query string, args ...any) (int64, error)

	// Cache
	CacheGet(ctx context.Context, key string) ([]byte, bool, error)
	CacheSet(ctx context.Context, key string, value []byte, ttlSeconds int) error
	CacheDelete(ctx context.Context, key string) error

	// HTTP (outbound)
	HTTPRequest(ctx context.Context, method, url string, headers map[string]string, body []byte) (int, []byte, error)

	// Email
	SendEmail(ctx context.Context, to, subject, body string, html bool) error

	// Logging
	Log(ctx context.Context, level, message string, fields map[string]any)

	// Config
	ConfigGet(ctx context.Context, key string) (string, error)

	// i18n
	Translate(ctx context.Context, key string, args ...any) string

	// Plugin-to-plugin calls
	// Allows one plugin to call functions in another plugin
	CallPlugin(ctx context.Context, pluginName, fn string, args json.RawMessage) (json.RawMessage, error)

	// SSE (Server-Sent Events)
	// Publishes an event to a named channel for connected browser clients.
	// channel scopes the event stream (e.g. "status", "progress");
	// eventType is the SSE event name (e.g. "device-table"); data is the payload (typically HTML).
	PublishEvent(ctx context.Context, channel string, eventType string, data string) error

	// Entity Deletion
	// EntitySoftDelete soft-deletes an entity (recycle bin + PII anonymisation).
	EntitySoftDelete(ctx context.Context, entityType string, entityID int64, reason string) error
	// EntityRestore restores a soft-deleted entity from the recycle bin.
	EntityRestore(ctx context.Context, entityType string, entityID int64) error
	// EntityHardDelete permanently removes an entity and all linked data.
	EntityHardDelete(ctx context.Context, entityType string, entityID int64, reason string) error
	// RecycleBinList lists soft-deleted entities in the recycle bin.
	RecycleBinList(ctx context.Context, entityType string) (json.RawMessage, error)

	// Secure Config
	// SecureConfigGet retrieves a decrypted secret value for this plugin.
	SecureConfigGet(ctx context.Context, key string) (string, error)
	// SecureConfigSet stores an encrypted secret value for this plugin.
	SecureConfigSet(ctx context.Context, key string, value string) error

	// Organisation
	// OrgID returns the active organisation ID for the current request.
	// Returns 0 if no organisation context (single-org mode).
	OrgID(ctx context.Context) int64

	// Custom Fields
	// Get retrieves custom field values for an entity. Plugin prefix is auto-stripped.
	// Pass nil for fields to get all fields; pass specific names to filter.
	CustomFieldsGet(ctx context.Context, entityType string, objectID int64, fields []string) (map[string]any, error)

	// Set stores custom field values for an entity. Plugin prefix is auto-stripped.
	// Validates types and constraints before storing.
	CustomFieldsSet(ctx context.Context, entityType string, objectID int64, values map[string]any) error

	// Query finds entities by custom field values. Returns matching object IDs.
	CustomFieldsQuery(ctx context.Context, entityType string, filters []CustomFieldFilter) ([]int64, error)

	// File Storage
	// StoreFile stores a file under the plugin's namespace.
	// Key is a logical path (e.g. "backups/job-123.backup"). Plugin prefix is auto-added.
	// Metadata is optional key-value pairs stored alongside the file (content-type, description, etc.).
	StoreFile(ctx context.Context, key string, data []byte, metadata map[string]string) error
	// GetFile retrieves a file by key. Returns the data and metadata, or error if not found.
	GetFile(ctx context.Context, key string) ([]byte, map[string]string, error)
	// DeleteFile removes a file by key.
	DeleteFile(ctx context.Context, key string) error
	// ListFiles lists files under a prefix (e.g. "backups/"). Returns keys and metadata.
	ListFiles(ctx context.Context, prefix string) ([]FileInfo, error)
	// GenerateThumbnail generates a thumbnail from image data using libvips.
	// Takes raw image bytes + content type + max dimensions (bounding box, aspect ratio preserved).
	// Returns thumbnail bytes and output content type (always image/jpeg or image/png).
	// For non-image types, returns a placeholder icon based on content type.
	GenerateThumbnail(ctx context.Context, data []byte, contentType string, maxWidth, maxHeight int) (thumbData []byte, thumbContentType string, err error)

	// Article Attachments
	// CreateArticleAttachment attaches a file to an article's thread (visible
	// in the ticket page and customer portal). createdBy is the acting user id
	// (FK to users.id); filename/contentType are metadata; content is the raw
	// file bytes (base64 over the RPC transport). Returns the attachment row id.
	CreateArticleAttachment(ctx context.Context, articleID, createdBy int64, filename, contentType string, content []byte) (int64, error)
	// ListArticleAttachments returns metadata for every attachment on an
	// article. Content is not included (download via the platform endpoint).
	ListArticleAttachments(ctx context.Context, articleID int64) ([]ArticleAttachment, error)
	// DeleteArticleAttachment removes one attachment from an article.
	DeleteArticleAttachment(ctx context.Context, articleID, attachmentID int64) error

	// Articles
	// CreateArticle creates an article (note/transcript/deliverable) on a ticket
	// with the platform's OTRS invariants (article + article_data_mime rows,
	// utf8mb3-safe body, agent sender, internal channel). visibleToCustomer sets
	// is_visible_for_customer. Returns the new article id. Replaces plugins
	// hand-writing article rows via raw SQL.
	CreateArticle(ctx context.Context, ticketID, createdBy int64, subject, body string, visibleToCustomer bool) (int64, error)

	// Ticket States
	// ChangeTicketStatus changes a ticket's state with core semantics:
	// pending-type states require untilTime > 0 (unix seconds); non-pending
	// states clear until_time. Replaces plugins hand-writing ticket UPDATEs.
	ChangeTicketStatus(ctx context.Context, ticketID, stateID, userID int64, untilTime int64) error
	// ListTicketStates returns all valid ticket states with type info, for
	// board/config UIs. Ordered by state id.
	ListTicketStates(ctx context.Context) ([]TicketStateInfo, error)
	// ListTicketViews returns the ticket-view URL templates declared by
	// enabled plugins' enabled UIs. Each URL contains a {ticket_id}
	// placeholder for the numeric ticket id. Nil when none declared.
	ListTicketViews(ctx context.Context) ([]TicketViewInfo, error)

	// Rendering
	// RenderMarkdownToPdf renders a markdown document to PDF bytes using the
	// platform's headless-Chromium sidecar (Browserless). The plugin supplies raw
	// markdown; the host handles conversion and printing. Returns application/pdf bytes.
	RenderMarkdownToPdf(ctx context.Context, markdown string, options PdfRenderOptions) ([]byte, error)
}

HostAPI is the interface plugins use to access host services. Passed to Plugin.Init() - plugins store this for later use.

type I18nSpec

type I18nSpec struct {
	// Namespace prefix for plugin translations (e.g., "stats" -> "stats.dashboard.title")
	Namespace string `json:"namespace,omitempty"`
	// Languages supported by this plugin
	Languages []string `json:"languages,omitempty"`
	// Inline translations (language -> key -> value)
	// For small plugins, translations can be embedded in the manifest
	Translations map[string]map[string]string `json:"translations,omitempty"`
}

I18nSpec defines internationalization resources provided by the plugin.

type JobSpec

type JobSpec struct {
	ID          string `json:"id"`                    // unique identifier
	Handler     string `json:"handler"`               // plugin function to call
	Schedule    string `json:"schedule"`              // cron expression, e.g. "0 * * * *"
	Description string `json:"description,omitempty"` // human-readable description
	Enabled     bool   `json:"enabled"`               // whether job runs by default
	Timeout     string `json:"timeout,omitempty"`     // max execution time, e.g. "5m"
}

JobSpec defines a scheduled/cron task.

type MCPToolSpec added in v0.8.2

type MCPToolSpec struct {
	Name        string         `json:"name"`                   // tool name (auto-prefixed with plugin name)
	Description string         `json:"description"`            // LLM-friendly description
	Handler     string         `json:"handler"`                // plugin function to call
	InputSchema map[string]any `json:"input_schema,omitempty"` // JSON Schema for parameters
}

MCPToolSpec defines an MCP tool that a plugin provides. When declared, these provide richer schemas than auto-generated route tools. The tool name is auto-prefixed with the plugin name to prevent collisions.

type MenuItemSpec struct {
	ID       string         `json:"id"`                 // unique identifier
	Label    string         `json:"label"`              // display text or i18n key (e.g. "<namespace>.menu.x" from the plugin's I18nSpec)
	Icon     string         `json:"icon,omitempty"`     // icon name or SVG
	Path     string         `json:"path"`               // URL path when clicked
	Location string         `json:"location"`           // where to insert: "agent" (top nav), "admin" (admin dashboard card), "customer" (portal nav), "profile" (agent Profile page, Connected accounts)
	Parent   string         `json:"parent,omitempty"`   // parent menu ID for submenus
	Order    int            `json:"order,omitempty"`    // sort order within location (ascending; ties by plugin name, then ID)
	Children []MenuItemSpec `json:"children,omitempty"` // nested menu items
}

MenuItemSpec defines a navigation menu entry.

type PdfRenderOptions added in v0.10.0

type PdfRenderOptions struct {
	PageSize string  // e.g. "A4" (default) or "Letter"
	MarginMM float64 // page margin in millimetres; default 15
	Title    string  // document title; shown in the PDF header when set

	// Branding (Epic E5 "Branded templates", first consumer goatcoach):
	// optional practice/coach identity applied to the printed document.
	// Zero values render exactly as before.
	BrandName    string // practice/coach name; shown in the running header
	BrandColor   string // "#RRGGBB" accent for headings/table headers; anything else ignored
	BrandLogoURL string // inline data:image/(png|jpeg|gif|webp);base64 URI for a header logo; anything else (https too) ignored
}

PdfRenderOptions controls PDF page layout for RenderMarkdownToPdf.

type Permission

type Permission struct {
	// Type is the permission category:
	//   db, cache, http, email, config, plugin_call,
	//   file    (StoreFile/DeleteFile = write, GetFile/ListFiles = read),
	//   article (CreateArticle and attachment create/delete = write, ListArticleAttachments = read),
	//   ticket  (ChangeTicketStatus = write, ListTicketStates/ListTicketViews = read),
	//   entity  (EntitySoftDelete/EntityRestore = write, RecycleBinList = read,
	//            EntityHardDelete = "hard_delete").
	Type string `json:"type" yaml:"type"`

	// Access level: "read", "write" or "readwrite". "readwrite" grants read
	// and write. Type "entity" also knows "hard_delete", which must be granted
	// on its own: "readwrite" does not include it.
	Access string `json:"access,omitempty" yaml:"access,omitempty"`

	// Scope constrains the permission. Meaning depends on type:
	//   db:     table allowlist, e.g. ["fictus_*", "ticket"]
	//   http:   URL patterns, e.g. ["*.tenor.com", "api.giphy.com"]
	//   cache:  key prefix (auto-namespaced if empty)
	//   plugin_call: plugin names allowed to call, e.g. ["stats"]
	//   entity: entity types, e.g. ["ticket"]
	// An empty scope allows everything the type and access cover.
	Scope []string `json:"scope,omitempty" yaml:"scope,omitempty"`
}

Permission declares a specific capability a plugin requests.

Plugins declare permissions in ResourceRequest. Until an admin stores a ResourcePolicy for the plugin, the host grants the declared permissions (except entity "hard_delete", which only an admin policy can grant).

type Plugin

type Plugin interface {
	// GKRegister returns plugin metadata. Called once at load time.
	// This is how plugins self-describe their capabilities per the GoatKit spec.
	GKRegister() GKRegistration

	// Init is called after loading, before the plugin serves requests.
	// The HostAPI provides access to host services (db, cache, http, etc).
	Init(ctx context.Context, host HostAPI) error

	// Call invokes a plugin function by name with JSON-encoded arguments.
	// Returns JSON-encoded response or error.
	// This is the primary communication channel between host and plugin.
	Call(ctx context.Context, fn string, args json.RawMessage) (json.RawMessage, error)

	// Shutdown is called before unloading the plugin.
	// Plugins should clean up resources and finish pending work.
	Shutdown(ctx context.Context) error
}

Plugin is the unified interface for WASM and gRPC plugins. Both runtime implementations must satisfy this interface.

type PluginManifest

type PluginManifest struct {
	Name         string           `yaml:"name"                   json:"name"`
	Version      string           `yaml:"version"                json:"version"`
	Runtime      string           `yaml:"runtime"                json:"runtime"`          // "wasm", "grpc", "template", or "theme"
	Binary       string           `yaml:"binary"                 json:"binary,omitempty"` // For grpc runtime: relative path to executable
	WASMFile     string           `yaml:"wasm,omitempty"         json:"wasm,omitempty"`   // For wasm runtime: defaults to name.wasm
	Icon         string           `yaml:"icon,omitempty"         json:"icon,omitempty"`   // SVG icon content or image URL (inline SVG content, FontAwesome class, or bundled icon path)
	Description  string           `yaml:"description,omitempty"  json:"description,omitempty"`
	Author       string           `yaml:"author,omitempty"       json:"author,omitempty"`
	License      string           `yaml:"license,omitempty"      json:"license,omitempty"`
	Homepage     string           `yaml:"homepage,omitempty"     json:"homepage,omitempty"`
	Resources    *ResourceRequest `yaml:"resources,omitempty"    json:"resources,omitempty"`
	Dependencies []string         `yaml:"dependencies,omitempty" json:"dependencies,omitempty"` // Plugin names this depends on
	PluginType   string           `yaml:"type,omitempty"         json:"type,omitempty"`         // "plugin" (default), "theme"
	Sidecars     []SidecarSpec    `yaml:"sidecars,omitempty"     json:"sidecars,omitempty"`     // Sidecar containers (gRPC plugins only)
}

PluginManifest represents a plugin.yaml manifest file. This is the universal plugin descriptor used by both the loader and packaging systems.

type ResourcePolicy

type ResourcePolicy struct {
	// Plugin name this policy applies to
	PluginName string `json:"plugin_name"`

	// Status: "pending_review", "approved", "restricted", "blocked"
	Status string `json:"status"`

	// Process limits (overrides plugin request)
	MemoryMB        int    `json:"memory_mb,omitempty"`
	CallTimeout     string `json:"call_timeout,omitempty"`
	InitTimeout     string `json:"init_timeout,omitempty"`
	ShutdownTimeout string `json:"shutdown_timeout,omitempty"`

	// Granted permissions (may be subset of requested)
	Permissions []Permission `json:"permissions,omitempty"`

	// Rate limits
	MaxCallsPerSecond  int `json:"max_calls_per_second,omitempty"` // 0 = unlimited
	MaxDBQueriesPerMin int `json:"max_db_queries_per_min,omitempty"`
	MaxHTTPReqPerMin   int `json:"max_http_req_per_min,omitempty"`

	// File storage limits
	MaxFileStorageBytes int64 `json:"max_file_storage_bytes,omitempty"` // 0 = default (500MB)
}

ResourcePolicy is the platform-enforced limits for a plugin. Set by admin, stored in sysconfig. Overrides ResourceRequest.

func DefaultResourcePolicy

func DefaultResourcePolicy(pluginName string) ResourcePolicy

DefaultResourcePolicy returns a restrictive default policy for new plugins. Plugins start with minimal access until an admin reviews them.

type ResourceRequest

type ResourceRequest struct {
	// Process limits (gRPC plugins only, ignored for WASM)
	MemoryMB        int    `json:"memory_mb,omitempty" yaml:"memory_mb,omitempty"`               // Requested RSS limit in MB
	CallTimeout     string `json:"call_timeout,omitempty" yaml:"call_timeout,omitempty"`         // Per-call deadline, e.g. "30s"
	InitTimeout     string `json:"init_timeout,omitempty" yaml:"init_timeout,omitempty"`         // Init must complete within, e.g. "10s"
	ShutdownTimeout string `json:"shutdown_timeout,omitempty" yaml:"shutdown_timeout,omitempty"` // Shutdown grace period, e.g. "5s"

	// HostAPI permissions requested
	Permissions []Permission `json:"permissions,omitempty" yaml:"permissions,omitempty"`

	// Requested file storage quota. The platform may grant less via ResourcePolicy.
	MaxFileStorageBytes int64 `json:"max_file_storage_bytes,omitempty" yaml:"max_file_storage_bytes,omitempty"`
}

ResourceRequest describes what a plugin asks for from the platform. These are requests/defaults — the platform may grant less via ResourcePolicy.

type RouteSpec

type RouteSpec struct {
	Method      string   `json:"method"`                // GET, POST, PUT, DELETE, etc.
	Path        string   `json:"path"`                  // URL path, e.g. "/admin/stats"
	Handler     string   `json:"handler"`               // plugin function to call
	Middleware  []string `json:"middleware,omitempty"`  // middleware chain
	Description string   `json:"description,omitempty"` // for documentation
}

RouteSpec defines an HTTP route the plugin wants to handle.

Middleware options:

  • "auth" — session, JWT or API token authentication required
  • "admin" — auth + admin role required
  • "agent" — auth + agent caller (customers refused)
  • "customer" — auth + customer caller (agents refused)
  • "group:<name>" — auth + agent group membership required
  • "plugin:<plugin>:<agentGroup>" — auth + per-org plugin access (customers) or agent group
  • "webhook" — no auth, HMAC signature verification, request logging
  • (empty) — no middleware: the route is public

Any other entry keeps the route from being registered.

type SetupTaskSpec added in v0.9.0

type SetupTaskSpec struct {
	ID          string `json:"id"`                    // unique within the plugin; the catalog key is "<plugin>:<id>"
	Title       string `json:"title"`                 // human-readable task name
	Description string `json:"description,omitempty"` // one-line explanation shown in the catalog
	Icon        string `json:"icon,omitempty"`        // SVG content, FontAwesome class, or bundled icon path
	Handler     string `json:"handler"`               // plugin function invoked by Manager.Call
	Category    string `json:"category"`              // grouping in the catalog, e.g. "customers", "tickets", "sla"
}

SetupTaskSpec declares a task the plugin contributes to the host's Setup Assistant task catalog. Tasks are mini-wizards for common admin operations (onboard a customer, create a queue + assign groups, configure an SLA, …). When the admin runs a plugin task, the host invokes the named Handler via Manager.Call(pluginName, handler, args); the handler returns a JSON object whose shape the Setup Assistant renders (e.g. {"html": "..."} or {"form": [...], "submit_handler": "..."}).

type SidecarHealth added in v0.8.1

type SidecarHealth struct {
	Command  []string `yaml:"command"            json:"command"`            // Health check command
	Interval string   `yaml:"interval,omitempty" json:"interval,omitempty"` // Check interval (default: "10s")
}

SidecarHealth defines a health check for a sidecar container.

type SidecarSpec added in v0.8.1

type SidecarSpec struct {
	Name        string            `yaml:"name"                   json:"name"`                 // Container name (e.g. "adb-server")
	Image       string            `yaml:"image"                  json:"image"`                // Container image (e.g. "goatkit/adb-server:latest")
	Ports       []string          `yaml:"ports,omitempty"        json:"ports,omitempty"`      // Exposed ports (e.g. ["5037"])
	Env         map[string]string `yaml:"env,omitempty"          json:"env,omitempty"`        // Environment variables
	Volumes     []string          `yaml:"volumes,omitempty"      json:"volumes,omitempty"`    // Volume mounts (e.g. ["/dev/bus/usb:/dev/bus/usb"])
	Privileged  bool              `yaml:"privileged,omitempty"   json:"privileged,omitempty"` // Run with elevated privileges (e.g. USB access)
	MemoryMB    int               `yaml:"memory_mb,omitempty"    json:"memory_mb,omitempty"`  // Memory limit (0 = default 128Mi)
	CPUMillis   int               `yaml:"cpu_millis,omitempty"   json:"cpu_millis,omitempty"` // CPU limit in millicores (0 = default 200m)
	Healthcheck *SidecarHealth    `yaml:"healthcheck,omitempty"  json:"healthcheck,omitempty"`
}

SidecarSpec declares a sidecar container that a plugin requires. In K8s mode, sidecars are injected into the plugin's pod spec. In Docker Compose mode, they're added as linked services on the same network.

type TemplateSpec

type TemplateSpec struct {
	Name     string `json:"name"`               // template name, e.g. "stats/dashboard.html"
	Path     string `json:"path"`               // path within plugin package
	Override bool   `json:"override,omitempty"` // if true, overrides host template of same name
}

TemplateSpec defines a template the plugin provides.

type TicketStateInfo added in v0.10.0

type TicketStateInfo struct {
	ID       int64  `json:"id"`
	Name     string `json:"name"`
	Color    string `json:"color,omitempty"`
	TypeID   int64  `json:"type_id"`
	TypeName string `json:"type_name"`
}

TicketStateInfo describes a valid ticket state with its type.

type TicketViewInfo added in v0.10.0

type TicketViewInfo struct {
	PluginName string `json:"plugin_name"`
	UIID       string `json:"ui_id"`
	Label      string `json:"label"`
	URL        string `json:"url"`
}

TicketViewInfo is a plugin-provided ticket view with its URL template. URL contains the literal {ticket_id} placeholder.

type UIAuthSpec added in v0.8.0

type UIAuthSpec struct {
	Method string   `json:"method,omitempty"` // session, token, none
	Groups []string `json:"groups,omitempty"` // required agent groups (all of them)
}

UIAuthSpec holds per-UI auth configuration.

Method "session" (default for admin_page, agent_app, customer_app) and "token" authenticate the caller by session cookie, Bearer JWT or API token; admin_page/agent_app UIs then admit agents only, customer_app UIs customers only. "none" (default for public_page, kiosk) leaves the UI public. Groups are agent groups the caller must all belong to (admins bypass). A UI with any other method is not registered.

type UIBrandingSpec added in v0.8.0

type UIBrandingSpec struct {
	AppName string `json:"app_name,omitempty"`
	Favicon string `json:"favicon,omitempty"` // URL or base64 data URI
	Color   string `json:"color,omitempty"`   // primary brand colour (hex)
}

UIBrandingSpec holds per-UI branding overrides.

type UINavItem added in v0.8.0

type UINavItem struct {
	Label string `json:"label"`           // display text (can be i18n key)
	Icon  string `json:"icon"`            // FontAwesome class
	Path  string `json:"path"`            // relative path within this UI, or an absolute "/ui/..." path into another plugin's UI (shown only when that UI and its plugin are enabled)
	Badge string `json:"badge,omitempty"` // plugin function returning badge count
	Order int    `json:"order,omitempty"`
}

UINavItem is a navigation entry in a plugin UI.

type UINavSpec added in v0.8.0

type UINavSpec struct {
	Position string      `json:"position"` // bottom, top, side
	Items    []UINavItem `json:"items"`
}

UINavSpec defines navigation for a plugin UI shell.

type UIPWASpec added in v0.8.0

type UIPWASpec struct {
	Enabled     bool     `json:"enabled"`
	StartURL    string   `json:"start_url,omitempty"` // defaults to UI root
	Display     string   `json:"display,omitempty"`   // standalone, fullscreen, minimal-ui
	ThemeColor  string   `json:"theme_color,omitempty"`
	CacheRoutes []string `json:"cache_routes,omitempty"` // routes to pre-cache for offline
}

UIPWASpec holds PWA manifest configuration for a plugin UI.

type UIRouteSpec added in v0.8.0

type UIRouteSpec struct {
	Path    string `json:"path"`             // relative path, e.g. "/", "/items/:id"
	Method  string `json:"method,omitempty"` // GET, POST, etc. (default: GET)
	Handler string `json:"handler"`          // plugin function name
}

UIRouteSpec defines a route within a plugin UI.

type UISpec added in v0.8.0

type UISpec struct {
	ID          string          `json:"id"`   // unique within plugin (auto-prefixed)
	Name        string          `json:"name"` // display name
	Description string          `json:"description,omitempty"`
	Type        string          `json:"type"`                 // admin_page, agent_app, customer_app, public_page, kiosk
	Icon        string          `json:"icon,omitempty"`       // FontAwesome class or SVG
	Shell       string          `json:"shell,omitempty"`      // none, minimal, standard (defaults per type)
	Routes      []UIRouteSpec   `json:"routes"`               // routes relative to /ui/{plugin}_{id}/
	Nav         *UINavSpec      `json:"nav,omitempty"`        // navigation for minimal/standard shells
	Branding    *UIBrandingSpec `json:"branding,omitempty"`   // per-UI branding overrides
	Auth        *UIAuthSpec     `json:"auth,omitempty"`       // auth configuration
	PWA         *UIPWASpec      `json:"pwa,omitempty"`        // PWA manifest configuration
	DataScope   string          `json:"data_scope,omitempty"` // self, org, all (for customer UIs)
	RateLimit   int             `json:"rate_limit,omitempty"` // requests/min per client IP for public (auth none) UIs (0 = 60)

	// TicketView declares that this UI can render a ticket as its primary
	// view (e.g. a coaching ticket page). The host exposes the resolved
	// URL template via HostAPI.ListTicketViews so other plugin UIs can
	// deep-link into it.
	TicketView *UITicketViewSpec `json:"ticket_view,omitempty"`
}

UISpec declares an independent UI that a plugin provides. Each UI gets its own routes, shell, branding, auth, and optional PWA support.

type UITicketViewSpec added in v0.10.0

type UITicketViewSpec struct {
	Path  string `json:"path"`  // e.g. "/ticket"
	Param string `json:"param"` // e.g. "ticket_id"
	Label string `json:"label,omitempty"`
}

UITicketViewSpec declares that a UI can render a single ticket as its primary view. Path is a route of the UI (leading slash optional — the host normalizes the join); Param is the query parameter that receives the numeric ticket id.

type WidgetSpec

type WidgetSpec struct {
	ID          string `json:"id"`                    // unique identifier
	Title       string `json:"title"`                 // display title (can be i18n key)
	Description string `json:"description,omitempty"` // widget description
	Handler     string `json:"handler"`               // plugin function that returns widget HTML
	Location    string `json:"location"`              // dashboard location: "agent_home", "admin_home"
	Size        string `json:"size,omitempty"`        // "small", "medium", "large", "full"
	Order       int    `json:"order,omitempty"`       // sort order within location
	Refreshable bool   `json:"refreshable,omitempty"` // can be refreshed via AJAX
	RefreshSec  int    `json:"refresh_sec,omitempty"` // auto-refresh interval
}

WidgetSpec defines a dashboard widget.

Directories

Path Synopsis
Package grpcutil provides shared types for gRPC plugin communication.
Package grpcutil provides shared types for gRPC plugin communication.

Jump to

Keyboard shortcuts

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