Documentation
¶
Index ¶
- func GetOperator() string
- func IsExecAllowed() bool
- func SetAllowExec(allow bool)
- func SetOperator(op string)
- type APIConfig
- type APIKeyConfig
- type Action
- type AuthConfig
- type BlocksConfig
- type CORSConfig
- type CacheConfig
- type Config
- type FeaturesConfig
- type NavPage
- type NavSection
- type OutputConfig
- type ParamDef
- type Permission
- type RateLimitConfig
- type RetryConfig
- type RouteEntry
- type RuntimeConfig
- type SecurityConfig
- type ServerConfig
- type SiteConfig
- type SourceConfig
- func (c SourceConfig) GetCacheMaxBytes() int
- func (c SourceConfig) GetCacheMaxRows() int
- func (c SourceConfig) GetCacheStrategy() string
- func (c SourceConfig) GetCacheTTL() time.Duration
- func (c SourceConfig) GetRetryBaseDelay() time.Duration
- func (c SourceConfig) GetRetryMaxDelay() time.Duration
- func (c SourceConfig) GetRetryMaxRetries() int
- func (c SourceConfig) GetTimeout() time.Duration
- func (c SourceConfig) IsCacheEnabled() bool
- func (c SourceConfig) IsReadonly() bool
- func (c SourceConfig) IsStaleWhileRevalidate() bool
- type StylingConfig
- type Webhook
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetOperator ¶
func GetOperator() string
GetOperator returns the current operator identity. Returns empty string if not set and $USER is not available.
func IsExecAllowed ¶
func IsExecAllowed() bool
IsExecAllowed returns whether exec actions are enabled.
func SetAllowExec ¶
func SetAllowExec(allow bool)
SetAllowExec enables or disables exec actions. Exec actions (shell commands) are disabled by default for security.
func SetOperator ¶
func SetOperator(op string)
SetOperator sets the operator identity for this session. If empty, defaults to the current user from $USER environment variable.
Types ¶
type APIConfig ¶
type APIConfig struct {
Enabled bool `yaml:"enabled"` // Enable REST API endpoints (default: false)
CORS *CORSConfig `yaml:"cors,omitempty"`
RateLimit *RateLimitConfig `yaml:"rate_limit,omitempty"`
Auth *AuthConfig `yaml:"auth,omitempty"`
}
APIConfig holds REST API configuration
func (*APIConfig) GetCORSOrigins ¶
GetCORSOrigins returns the configured CORS origins, or nil if not configured
func (*APIConfig) GetMaxTrackedIPs ¶
GetMaxTrackedIPs returns the maximum number of unique IPs tracked by the rate limiter (default: 10000)
func (*APIConfig) GetRateLimitBurst ¶
GetRateLimitBurst returns the burst size (default: 20)
func (*APIConfig) GetRateLimitRPS ¶
GetRateLimitRPS returns the rate limit in requests per second (default: 10)
func (*APIConfig) IsAuthEnabled ¶
IsAuthEnabled returns true if API authentication is configured. It checks the raw config value (not env-expanded) so that a configured but missing env var is treated as "auth intended" rather than silently disabled.
type APIKeyConfig ¶
type APIKeyConfig struct {
Name string `yaml:"name"`
Key string `yaml:"key"`
Permissions []Permission `yaml:"permissions,omitempty"`
}
APIKeyConfig represents a named API key with associated permissions.
func (*APIKeyConfig) HasPermission ¶
func (k *APIKeyConfig) HasPermission(perm Permission) bool
HasPermission checks if this key has a specific permission.
type Action ¶
type Action struct {
Kind string `yaml:"kind"` // Action kind: "sql", "http", "exec"
Source string `yaml:"source,omitempty"` // For sql: source name to execute against
Statement string `yaml:"statement,omitempty"` // For sql: SQL statement with :param placeholders
URL string `yaml:"url,omitempty"` // For http: request URL (supports template expressions)
Method string `yaml:"method,omitempty"` // For http: HTTP method (default: POST)
Body string `yaml:"body,omitempty"` // For http: request body template
Cmd string `yaml:"cmd,omitempty"` // For exec: command to run
Params map[string]ParamDef `yaml:"params,omitempty"` // Parameter definitions
Confirm string `yaml:"confirm,omitempty"` // Confirmation message (triggers dialog)
}
Action defines a custom action that can be triggered via lvt-click
type AuthConfig ¶
type AuthConfig struct {
// APIKey is the legacy single API key for authentication (backward compatible).
// Supports environment variable expansion (e.g., "${API_KEY}" or "$API_KEY").
// Gets full permissions (read, write, delete) when used.
APIKey string `yaml:"api_key,omitempty"`
// HeaderName is the HTTP header name for the API key (default: "X-API-Key")
// Also supports "Authorization: Bearer <token>" format when set to "Authorization"
HeaderName string `yaml:"header_name,omitempty"`
// Keys is a list of named API keys with specific permissions.
Keys []APIKeyConfig `yaml:"keys,omitempty"`
}
AuthConfig holds authentication configuration for the API
func (*AuthConfig) GetAPIKey ¶
func (c *AuthConfig) GetAPIKey() string
GetAPIKey returns the configured API key with environment variable expansion
func (*AuthConfig) GetAPIKeys ¶
func (c *AuthConfig) GetAPIKeys() []APIKeyConfig
GetAPIKeys returns all configured API keys, normalizing legacy and new formats. Legacy api_key gets full permissions for backward compatibility. Uses the raw (unexpanded) value to detect intent — if the user configured an api_key that expands to empty, auth is still enforced (rejecting all requests) rather than silently disabled.
func (*AuthConfig) GetHeaderName ¶
func (c *AuthConfig) GetHeaderName() string
GetHeaderName returns the header name for authentication (default: "X-API-Key")
type BlocksConfig ¶
type BlocksConfig struct {
AutoID bool `yaml:"auto_id"`
IDFormat string `yaml:"id_format"`
ShowLineNumbers bool `yaml:"show_line_numbers"`
}
BlocksConfig holds block-related configuration
type CORSConfig ¶
type CORSConfig struct {
Origins []string `yaml:"origins,omitempty"` // Allowed origins (e.g., ["http://localhost:3000", "*"])
}
CORSConfig holds CORS configuration for the API
type CacheConfig ¶
type CacheConfig struct {
TTL string `yaml:"ttl,omitempty"` // Cache TTL (e.g., "5m", "1h"). Default: disabled (empty)
Strategy string `yaml:"strategy,omitempty"` // Cache strategy: "simple" or "stale-while-revalidate". Default: "simple"
MaxRows int `yaml:"max_rows,omitempty"` // Maximum rows to cache (truncates if exceeded). Default: unlimited
MaxBytes int `yaml:"max_bytes,omitempty"` // Maximum bytes to cache (truncates if exceeded). Default: unlimited
}
CacheConfig configures caching behavior for a source
type Config ¶
type Config struct {
Title string `yaml:"title"`
Description string `yaml:"description"`
Type string `yaml:"type"` // "tutorial" or "site"
Site *SiteConfig `yaml:"site,omitempty"`
Server ServerConfig `yaml:"server"`
Styling StylingConfig `yaml:"styling"`
Blocks BlocksConfig `yaml:"blocks"`
Features FeaturesConfig `yaml:"features"`
Ignore []string `yaml:"ignore"`
Sources map[string]SourceConfig `yaml:"sources,omitempty"`
Actions map[string]*Action `yaml:"actions,omitempty"`
API *APIConfig `yaml:"api,omitempty"`
Webhooks map[string]*Webhook `yaml:"webhooks,omitempty"`
Outputs map[string]*OutputConfig `yaml:"outputs,omitempty"`
Security SecurityConfig `yaml:"security,omitempty"`
// VersionPrefix, when non-empty, becomes a URL path segment that is
// stripped from incoming requests before route resolution. Routes serve
// equivalently with or without the prefix; the prefix exists so that a
// future multi-version deployment can mount several site builds under
// distinct prefixes (e.g. /v0/, /latest/) without collision.
VersionPrefix string `yaml:"version_prefix,omitempty"`
// Routes declares custom URL routes that bypass the markdown page
// resolver. Each entry binds a request-path pattern to an upstream
// destination. Currently only `type: proxy` is supported, which
// reverse-proxies the request (including WebSocket upgrades) to the
// configured upstream host. The full request path is forwarded
// unchanged — the upstream is responsible for its own URL structure.
Routes []RouteEntry `yaml:"routes,omitempty"`
}
Config represents the tinkerdown configuration
func Load ¶
Load loads configuration from a YAML file If the file doesn't exist, returns the default configuration
func LoadFromDir ¶
LoadFromDir looks for tinkerdown.yaml, lmt.yaml, or livemdtools.yaml in the given directory tinkerdown.yaml is checked first, then lmt.yaml (short form), then livemdtools.yaml (legacy) If none is found, returns the default configuration
func (*Config) IsAPIEnabled ¶
IsAPIEnabled returns whether the API is enabled
func (*Config) IsSiteMode ¶
IsSiteMode returns true if the config is for a multi-page site
func (*Config) IsTutorialMode ¶
IsTutorialMode returns true if the config is for a single tutorial
func (*Config) ValidateOutputs ¶
ValidateOutputs validates all output configurations in the config.
func (*Config) ValidateWebhooks ¶
ValidateWebhooks validates all webhook configurations in the config. Returns an error if any webhook has invalid configuration.
type FeaturesConfig ¶
type FeaturesConfig struct {
HotReload bool `yaml:"hot_reload"`
Sidebar bool `yaml:"sidebar"` // Show navigation sidebar (default: false)
Headless bool `yaml:"headless"` // Run without web UI, only API/webhooks/schedules
// PrerenderDiagrams enables server-side mermaid pre-rendering via
// Kroki. When true, “`mermaid blocks are converted to inline SVG at
// parse time and the ~3.3MB client-side mermaid runtime is skipped on
// pages where ALL blocks pre-rendered successfully. Blocks that fail
// to render fall back to the client-side runtime. Default: false.
PrerenderDiagrams bool `yaml:"prerender_diagrams,omitempty"`
// KrokiURL overrides the Kroki base URL used for diagram pre-render
// (default: https://kroki.io public instance). Point this at a
// self-hosted Kroki container for production deployments where the
// public instance's rate limits or terms are not acceptable.
KrokiURL string `yaml:"kroki_url,omitempty"`
}
FeaturesConfig holds feature flags
type NavPage ¶
type NavPage struct {
}
NavPage represents a single entry in navigation. It is either a leaf (Path set, no Pages) or a collapsible group (Pages set) — or both, a landing page that also owns sub-pages. Groups let a long section nest its pages by category instead of rendering as one flat list.
type OutputConfig ¶
type OutputConfig struct {
// Type is the output type: "slack" or "email"
Type string `yaml:"type"`
// Channel is the Slack channel (for slack type), e.g., "#team-updates"
// Environment variable expansion is supported (e.g., "${SLACK_CHANNEL}")
Channel string `yaml:"channel,omitempty"`
// To is the email recipient address (for email type)
// Environment variable expansion is supported (e.g., "${ALERT_EMAIL}")
To string `yaml:"to,omitempty"`
// Subject is the email subject line (for email type)
// Defaults to "Notification from Tinkerdown"
Subject string `yaml:"subject,omitempty"`
}
OutputConfig defines an output destination for notifications. Outputs receive messages from Notify imperatives in markdown content.
Example Configuration ¶
outputs:
team-slack:
type: slack
channel: "#team-updates"
alerts-email:
type: email
to: "alerts@company.com"
subject: "Tinkerdown Alert"
func (*OutputConfig) GetChannel ¶
func (o *OutputConfig) GetChannel() string
GetChannel returns the channel with environment variable expansion
func (*OutputConfig) GetTo ¶
func (o *OutputConfig) GetTo() string
GetTo returns the recipient address with environment variable expansion
func (*OutputConfig) Validate ¶
func (o *OutputConfig) Validate(name string) error
Validate checks that the output configuration is valid.
type ParamDef ¶
type ParamDef struct {
Type string `yaml:"type,omitempty"` // Parameter type: "string", "number", "date", "bool"
Required bool `yaml:"required,omitempty"` // Whether the parameter is required
Default string `yaml:"default,omitempty"` // Default value
}
ParamDef defines a parameter for an action
type Permission ¶
type Permission string
Permission represents an API operation permission.
const ( PermRead Permission = "read" PermWrite Permission = "write" PermDelete Permission = "delete" )
type RateLimitConfig ¶
type RateLimitConfig struct {
RequestsPerSecond float64 `yaml:"requests_per_second,omitempty"` // Rate limit in requests per second (default: 10)
Burst int `yaml:"burst,omitempty"` // Burst size (default: 20)
MaxTrackedIPs int `yaml:"max_tracked_ips,omitempty"` // Maximum unique IPs to track (default: 10000)
}
RateLimitConfig holds rate limiting configuration for the API
type RetryConfig ¶
type RetryConfig struct {
MaxRetries int `yaml:"max_retries,omitempty"` // Maximum retry attempts (default: 3)
BaseDelay string `yaml:"base_delay,omitempty"` // Initial delay (e.g., "100ms"). Default: 100ms
MaxDelay string `yaml:"max_delay,omitempty"` // Maximum delay (e.g., "5s"). Default: 5s
}
RetryConfig configures retry behavior for a source
type RouteEntry ¶
type RouteEntry struct {
Pattern string `yaml:"pattern"`
Type string `yaml:"type"`
Upstream string `yaml:"upstream"`
}
RouteEntry binds a URL pattern to a destination. A pattern ending in "/" matches that subtree; otherwise it must match exactly. Routes are evaluated in declaration order; first match wins.
type RuntimeConfig ¶
type RuntimeConfig struct {
// contains filtered or unexported fields
}
RuntimeConfig stores configuration set at runtime via CLI flags. These values are not persisted to config files.
type SecurityConfig ¶ added in v0.1.16
type SecurityConfig struct {
// FrameSrc lists origins appended to the CSP frame-src directive,
// in addition to the implicit 'self'. Set this when the site embeds
// cross-origin iframes (e.g., a separately-deployed app loaded as a
// live demo on a docs page). Validate() rejects entries that contain
// CSP/header-injection characters or that don't parse as a URI. Use
// scheme + host (e.g., "https://lt-landing-demo.fly.dev"). When the
// list is empty no frame-src directive is emitted, falling back to
// default-src 'self' which blocks cross-origin frames.
FrameSrc []string `yaml:"frame_src,omitempty"`
}
SecurityConfig exposes site-level security knobs that change emitted security response headers. Currently scoped to CSP overrides; further fields can be added without breaking existing configs because the struct is yaml-omitempty.
func (SecurityConfig) Validate ¶ added in v0.1.16
func (c SecurityConfig) Validate() error
Validate ensures every FrameSrc entry is safe to emit verbatim into a CSP header value. CSP directives are separated by `;`, and HTTP header values must not contain CR/LF, so any of those characters in an operator-supplied origin would either smuggle a new directive (e.g., widening script-src) or split the response header entirely. URL parsing additionally rejects obviously malformed values so that a typo surfaces at startup instead of as a silently-broken iframe.
type ServerConfig ¶
type ServerConfig struct {
Port int `yaml:"port"`
Host string `yaml:"host"`
Debug bool `yaml:"debug"`
}
ServerConfig holds server-related configuration
type SiteConfig ¶
type SiteConfig struct {
Home string `yaml:"home"` // Homepage markdown file (e.g., "index.md")
Logo string `yaml:"logo"` // Logo path (e.g., "/assets/logo.svg")
Repository string `yaml:"repository"` // GitHub repository URL
// URL is the canonical absolute base URL of the deployed site
// (e.g., "https://livetemplate.fly.dev"), with NO trailing slash.
// When set, sitemap.xml emits absolute URLs and OpenGraph meta tags
// include og:url. When empty, sitemap entries use relative paths and
// og:url is omitted.
URL string `yaml:"url,omitempty"`
}
SiteConfig holds site-level configuration
type SourceConfig ¶
type SourceConfig struct {
Type string `yaml:"type"` // "exec", "pg", "rest", "csv", "json", "markdown", "sqlite", "wasm", "graphql"
Cmd string `yaml:"cmd,omitempty"` // For exec: command to run
Query string `yaml:"query,omitempty"` // For pg: SQL query
From string `yaml:"from,omitempty"` // For rest/graphql: API endpoint URL
File string `yaml:"file,omitempty"` // For csv/json/markdown: file path
Anchor string `yaml:"anchor,omitempty"` // For markdown: section anchor (e.g., "#todos")
DB string `yaml:"db,omitempty"` // For sqlite: database file path (default: ./tinkerdown.db)
Table string `yaml:"table,omitempty"` // For sqlite: table name
Path string `yaml:"path,omitempty"` // For wasm: path to .wasm file
QueryFile string `yaml:"query_file,omitempty"` // For graphql: path to .graphql file
Variables map[string]interface{} `yaml:"variables,omitempty"` // For graphql: query variables
Headers map[string]string `yaml:"headers,omitempty"` // For rest/graphql: HTTP headers (env vars expanded)
QueryParams map[string]string `yaml:"query_params,omitempty"` // For rest: URL query parameters (env vars expanded)
ResultPath string `yaml:"result_path,omitempty"` // For rest/graphql: dot-path to extract array (e.g., "data.items")
Readonly *bool `yaml:"readonly,omitempty"` // For markdown/sqlite: read-only mode (default: true, set to false for writes)
Options map[string]string `yaml:"options,omitempty"` // Type-specific options (also used for wasm init config)
Manual bool `yaml:"manual,omitempty"` // For exec: require Run button click
Format string `yaml:"format,omitempty"` // For exec: output format (json, lines, csv). Default: json
Delimiter string `yaml:"delimiter,omitempty"` // For exec CSV: field delimiter. Default: ","
Env map[string]string `yaml:"env,omitempty"` // For exec: environment variables (env vars expanded)
Timeout string `yaml:"timeout,omitempty"` // Request timeout (e.g., "30s", "1m"). Default: 10s
Retry *RetryConfig `yaml:"retry,omitempty"` // Retry configuration
Cache *CacheConfig `yaml:"cache,omitempty"` // Cache configuration
AutoBind *bool `yaml:"auto_bind,omitempty"` // Set to false to exclude from auto-table matching
// For computed sources: derive data from another source
GroupBy string `yaml:"group_by,omitempty"` // Field to group by (e.g., "category")
Aggregate map[string]string `yaml:"aggregate,omitempty"` // Field → aggregation expression (e.g., "total": "sum(amount)")
Filter string `yaml:"filter,omitempty"` // Optional filter expression (e.g., "status = active")
}
SourceConfig defines a data source for lvt-source blocks
func (SourceConfig) GetCacheMaxBytes ¶
func (c SourceConfig) GetCacheMaxBytes() int
GetCacheMaxBytes returns the max bytes limit (0 = unlimited)
func (SourceConfig) GetCacheMaxRows ¶
func (c SourceConfig) GetCacheMaxRows() int
GetCacheMaxRows returns the max rows limit (0 = unlimited)
func (SourceConfig) GetCacheStrategy ¶
func (c SourceConfig) GetCacheStrategy() string
GetCacheStrategy returns the cache strategy (default: "simple")
func (SourceConfig) GetCacheTTL ¶
func (c SourceConfig) GetCacheTTL() time.Duration
GetCacheTTL returns the cache TTL (0 if caching is disabled)
func (SourceConfig) GetRetryBaseDelay ¶
func (c SourceConfig) GetRetryBaseDelay() time.Duration
GetRetryBaseDelay returns the base delay (default: 100ms)
func (SourceConfig) GetRetryMaxDelay ¶
func (c SourceConfig) GetRetryMaxDelay() time.Duration
GetRetryMaxDelay returns the max delay (default: 5s)
func (SourceConfig) GetRetryMaxRetries ¶
func (c SourceConfig) GetRetryMaxRetries() int
GetRetryMaxRetries returns the max retries (default: 3, set to 0 to disable retries)
func (SourceConfig) GetTimeout ¶
func (c SourceConfig) GetTimeout() time.Duration
GetTimeout returns the parsed timeout duration (default: 10s)
func (SourceConfig) IsCacheEnabled ¶
func (c SourceConfig) IsCacheEnabled() bool
IsCacheEnabled returns true if caching is enabled for this source
func (SourceConfig) IsReadonly ¶
func (c SourceConfig) IsReadonly() bool
IsReadonly returns true if the source is read-only (default: true for markdown sources)
func (SourceConfig) IsStaleWhileRevalidate ¶
func (c SourceConfig) IsStaleWhileRevalidate() bool
IsStaleWhileRevalidate returns true if using stale-while-revalidate strategy
type StylingConfig ¶
type StylingConfig struct {
Theme string `yaml:"theme"`
PrimaryColor string `yaml:"primary_color"`
Font string `yaml:"font"`
// CustomCSS is a site-relative path (e.g. "assets/landing.css") served
// from <rootDir>/assets and injected as a <link> in the <head> of pages
// using `layout: landing`. Lets a site carry bespoke styling for its
// marketing/landing pages without touching the default docs shell.
CustomCSS string `yaml:"custom_css,omitempty"`
// SiteCSS is a site-relative path served from <rootDir>/assets and injected
// as a <link> in the <head> of EVERY page (both the default docs shell and
// `layout: landing`). Use it for shared brand primitives — self-hosted
// @font-face declarations, base tokens — that should reach the calm docs
// shell too, while CustomCSS stays quarantined to landing pages. On landing
// pages SiteCSS loads before CustomCSS so the landing layer can override it.
SiteCSS string `yaml:"site_css,omitempty"`
}
StylingConfig holds styling-related configuration
type Webhook ¶
type Webhook struct {
// Action is the name of the action to execute when this webhook is triggered
Action string `yaml:"action"`
// Secret is the shared secret for validation (supports env var expansion)
// Used for X-Webhook-Secret header or ?secret= query param validation
Secret string `yaml:"secret,omitempty"`
// SignatureSecret is the secret used for HMAC signature validation (supports env var expansion)
// When set, validates X-Webhook-Signature header in format "sha256=<hex>"
// This provides stronger security than plain secret validation
SignatureSecret string `yaml:"signature_secret,omitempty"`
// ValidateTimestamp enables replay attack prevention by validating X-Webhook-Timestamp
// Requests older than TimestampTolerance seconds are rejected
ValidateTimestamp bool `yaml:"validate_timestamp,omitempty"`
// TimestampTolerance is the maximum age in seconds for timestamp validation (default: 300 = 5 minutes)
TimestampTolerance int `yaml:"timestamp_tolerance,omitempty"`
}
Webhook defines a webhook trigger that can receive HTTP POST requests.
Webhooks allow external services (CI/CD, monitoring, etc.) to trigger actions by sending POST requests to /webhook/{name} endpoints.
Security Features ¶
Webhooks support multiple authentication methods:
- Simple secret: X-Webhook-Secret header or ?secret= query parameter
- HMAC signature: X-Webhook-Signature header with "sha256=<hex>" format
- Timestamp validation: X-Webhook-Timestamp header for replay attack prevention
Exec Action Restrictions ¶
When a webhook triggers an "exec" action, the command is validated for safety. The following shell metacharacters are blocked to prevent command injection:
- & ; | : command chaining/background execution
- $ : variable expansion (could leak environment variables)
- > < : redirection (could overwrite files)
- ` : command substitution
- \ : escape sequences
- \n \r : newlines (could inject additional commands)
For complex commands, create an intermediate script and invoke it via the webhook.
Example Configuration ¶
webhooks:
deploy:
action: deploy-app
signature_secret: ${WEBHOOK_SECRET}
validate_timestamp: true
timestamp_tolerance: 300
github-push:
action: sync-repo
secret: ${GITHUB_WEBHOOK_SECRET}
func (*Webhook) GetSecret ¶
GetSecret returns the webhook secret with environment variable expansion
func (*Webhook) GetSignatureSecret ¶
GetSignatureSecret returns the HMAC signature secret with environment variable expansion
func (*Webhook) GetTimestampTolerance ¶
GetTimestampTolerance returns the timestamp tolerance in seconds (default 300)